ned14/llfio

`algorithm::traverse` uses a `vector<list<move-only-type>>` which isn't guaranteed to work

BurningEnlightenment opened this issue · 0 comments

According to Stephan T. Lavavej container<container<move-only-type>> types are not guaranteed to compile due to a longstanding bug in the C++ Standard. The algorithm::traverse() implementation triggers this defect with MSVC:

list(862): note: while compiling class template member function 'std::list<workitem,std::allocator<workitem>>::list(const std::list<workitem,std::allocator<workitem>> &)'
xmemory(682): note: see reference to function template instantiation 'std::list<workitem,std::allocator<workitem>>::list(const std::list<workitem,std::allocator<workitem>> &)' being compiled
llfio\v2.0\algorithm\../detail/impl/traverse.ipp(580): note: see reference to class template instantiation 'std::list<workitem,std::allocator<workitem>>' being compiled
xmemory(682): error C2280: 'workitem::workitem(const workitem &)': attempting to reference a deleted function
llfio\v2.0\algorithm\../detail/impl/traverse.ipp(172): note: see declaration of 'workitem::workitem'
llfio\v2.0\algorithm\../detail/impl/traverse.ipp(172): note: 'workitem::workitem(const workitem &)': function was explicitly deleted

std::vector<std::list<workitem>> workqueue;

The current workaround is to define a moving copy constructor:

#if _MSC_VER < 1933 // <= VS2022.2
// MSVC's list::splice() always copies :(
workitem(const workitem &o) noexcept
: workitem(const_cast<workitem &&>(std::move(o)))
{
}
#else
workitem(const workitem &) = delete;
#endif

In any case, the workaround selector is too restrictive. It is unclear whether this will be fixed at all, but definitly not earlier than the next MSVC ABI break (see also microsoft/STL#1036).