Non-copyable elements in a std::vector of std::lists
I have a non-copyable class, simplified as follows:
struct NonCopyable
{
NonCopyable() = default;
NonCopyable(const NonCopyable&) = delete;
NonCopyable& operator = (const NonCopyable&) = delete;
NonCopyable(NonCopyable&&) = default;
NonCopyable& operator = (NonCopyable&&) = default;
};
I store the objects of this class in various std::lists. At one point I have an empty std::vector of these lists, which I would like to resize to contain a fixed number of empty lists. However, this complains about the lack of a NonCopyable copy constructor, even though (as far as I can see) it shouldn't be trying to construct any NonCopyables!
std::vector<std::list<NonCopyable>> v; // OK
v.resize(4); // ERROR
v.emplace_back(); // ERROR
std::list<NonCopyable> l; // OK
v.push_back(l); // ERROR (unsurprisingly)
v.push_back(std::move(l)); // ERROR
Why is this? Is there any way to do this without making the class copyable?
I'm using VS2017 with /std:c++17 in case that makes any difference.
Here's the full error output from just trying to resize (first two lines above).
1>------ Build started: Project: testcore, Configuration: Debug x64 ------
1>testcard.cpp
1>c:program files (x86)microsoft visual studio2017communityvctoolsmsvc14.15.26726includexmemory0(881): error C2280: 'NonCopyable::NonCopyable(const NonCopyable &)': attempting to reference a deleted function
1>[...]testcard.cpp(30): note: see declaration of 'NonCopyable::NonCopyable'
1>[...]testcard.cpp(30): note: 'NonCopyable::NonCopyable(const NonCopyable &)': function was explicitly deleted
1>c:program files (x86)microsoft visual studio2017communityvctoolsmsvc14.15.26726includelist(711): note: see reference to function template instantiation 'void std::_Default_allocator_traits<_Alloc>::construct<_Ty,const NonCopyable&>(_Alloc &,_Objty *const ,const NonCopyable &)' being compiled
1> with
1> [
1> _Alloc=std::allocator<std::_List_node<NonCopyable,std::_Default_allocator_traits<std::allocator<NonCopyable>>::void_pointer>>,
1> _Ty=NonCopyable,
1> _Objty=NonCopyable
1> ]
1>c:program files (x86)microsoft visual studio2017communityvctoolsmsvc14.15.26726includelist(716): note: see reference to function template instantiation 'void std::_Default_allocator_traits<_Alloc>::construct<_Ty,const NonCopyable&>(_Alloc &,_Objty *const ,const NonCopyable &)' being compiled
1> with
1> [
1> _Alloc=std::allocator<std::_List_node<NonCopyable,std::_Default_allocator_traits<std::allocator<NonCopyable>>::void_pointer>>,
1> _Ty=NonCopyable,
1> _Objty=NonCopyable
1> ]
1>c:program files (x86)microsoft visual studio2017communityvctoolsmsvc14.15.26726includelist(947): note: see reference to function template instantiation 'std::_List_node<_Ty,std::_Default_allocator_traits<_Alloc>::void_pointer> *std::_List_buy<_Ty,_Alloc>::_Buynode<const NonCopyable&>(std::_List_node<_Ty,std::_Default_allocator_traits<_Alloc>::void_pointer> *,std::_List_node<_Ty,std::_Default_allocator_traits<_Alloc>::void_pointer> *,const NonCopyable &)' being compiled
1> with
1> [
1> _Ty=NonCopyable,
1> _Alloc=std::allocator<NonCopyable>
1> ]
1>c:program files (x86)microsoft visual studio2017communityvctoolsmsvc14.15.26726includelist(950): note: see reference to function template instantiation 'std::_List_node<_Ty,std::_Default_allocator_traits<_Alloc>::void_pointer> *std::_List_buy<_Ty,_Alloc>::_Buynode<const NonCopyable&>(std::_List_node<_Ty,std::_Default_allocator_traits<_Alloc>::void_pointer> *,std::_List_node<_Ty,std::_Default_allocator_traits<_Alloc>::void_pointer> *,const NonCopyable &)' being compiled
1> with
1> [
1> _Ty=NonCopyable,
1> _Alloc=std::allocator<NonCopyable>
1> ]
1>c:program files (x86)microsoft visual studio2017communityvctoolsmsvc14.15.26726includelist(1308): note: see reference to function template instantiation 'void std::list<NonCopyable,std::allocator<_Ty>>::_Insert<const NonCopyable&>(std::_List_unchecked_const_iterator<std::_List_val<std::_List_simple_types<_Ty>>,std::_Iterator_base0>,const NonCopyable &)' being compiled
1> with
1> [
1> _Ty=NonCopyable
1> ]
1>c:program files (x86)microsoft visual studio2017communityvctoolsmsvc14.15.26726includelist(1308): note: see reference to function template instantiation 'void std::list<NonCopyable,std::allocator<_Ty>>::_Insert<const NonCopyable&>(std::_List_unchecked_const_iterator<std::_List_val<std::_List_simple_types<_Ty>>,std::_Iterator_base0>,const NonCopyable &)' being compiled
1> with
1> [
1> _Ty=NonCopyable
1> ]
1>c:program files (x86)microsoft visual studio2017communityvctoolsmsvc14.15.26726includelist(1265): note: see reference to function template instantiation 'void std::list<NonCopyable,std::allocator<_Ty>>::_Insert_range<_Iter>(std::_List_unchecked_const_iterator<std::_List_val<std::_List_simple_types<_Ty>>,std::_Iterator_base0>,_Iter,_Iter,std::forward_iterator_tag)' being compiled
1> with
1> [
1> _Ty=NonCopyable,
1> _Iter=std::_List_const_iterator<std::_List_val<std::_List_simple_types<NonCopyable>>>
1> ]
1>c:program files (x86)microsoft visual studio2017communityvctoolsmsvc14.15.26726includelist(1264): note: see reference to function template instantiation 'void std::list<NonCopyable,std::allocator<_Ty>>::_Insert_range<_Iter>(std::_List_unchecked_const_iterator<std::_List_val<std::_List_simple_types<_Ty>>,std::_Iterator_base0>,_Iter,_Iter,std::forward_iterator_tag)' being compiled
1> with
1> [
1> _Ty=NonCopyable,
1> _Iter=std::_List_const_iterator<std::_List_val<std::_List_simple_types<NonCopyable>>>
1> ]
1>c:program files (x86)microsoft visual studio2017communityvctoolsmsvc14.15.26726includelist(800): note: see reference to function template instantiation 'std::_List_iterator<std::_List_val<std::_List_simple_types<_Ty>>> std::list<_Ty,std::allocator<_Ty>>::insert<std::_List_const_iterator<std::_List_val<std::_List_simple_types<_Ty>>>,void>(std::_List_const_iterator<std::_List_val<std::_List_simple_types<_Ty>>>,_Iter,_Iter)' being compiled
1> with
1> [
1> _Ty=NonCopyable,
1> _Iter=std::_List_const_iterator<std::_List_val<std::_List_simple_types<NonCopyable>>>
1> ]
1>c:program files (x86)microsoft visual studio2017communityvctoolsmsvc14.15.26726includelist(800): note: see reference to function template instantiation 'std::_List_iterator<std::_List_val<std::_List_simple_types<_Ty>>> std::list<_Ty,std::allocator<_Ty>>::insert<std::_List_const_iterator<std::_List_val<std::_List_simple_types<_Ty>>>,void>(std::_List_const_iterator<std::_List_val<std::_List_simple_types<_Ty>>>,_Iter,_Iter)' being compiled
1> with
1> [
1> _Ty=NonCopyable,
1> _Iter=std::_List_const_iterator<std::_List_val<std::_List_simple_types<NonCopyable>>>
1> ]
1>c:program files (x86)microsoft visual studio2017communityvctoolsmsvc14.15.26726includelist(796): note: while compiling class template member function 'std::list<NonCopyable,std::allocator<_Ty>>::list(const std::list<_Ty,std::allocator<_Ty>> &)'
1> with
1> [
1> _Ty=NonCopyable
1> ]
1>c:program files (x86)microsoft visual studio2017communityvctoolsmsvc14.15.26726includexmemory0(881): note: see reference to function template instantiation 'std::list<NonCopyable,std::allocator<_Ty>>::list(const std::list<_Ty,std::allocator<_Ty>> &)' being compiled
1> with
1> [
1> _Ty=NonCopyable
1> ]
1>c:program files (x86)microsoft visual studio2017communityvctoolsmsvc14.15.26726includevector(1812): note: see reference to class template instantiation 'std::list<NonCopyable,std::allocator<_Ty>>' being compiled
1> with
1> [
1> _Ty=NonCopyable
1> ]
1>c:program files (x86)microsoft visual studio2017communityvctoolsmsvc14.15.26726includevector(1811): note: while compiling class template member function 'std::list<NonCopyable,std::allocator<_Ty>> *std::vector<std::list<_Ty,std::allocator<_Ty>>,std::allocator<std::list<_Ty,std::allocator<_Ty>>>>::_Udefault(std::list<_Ty,std::allocator<_Ty>> *,const unsigned __int64)'
1> with
1> [
1> _Ty=NonCopyable
1> ]
1>c:program files (x86)microsoft visual studio2017communityvctoolsmsvc14.15.26726includevector(1479): note: see reference to function template instantiation 'std::list<NonCopyable,std::allocator<_Ty>> *std::vector<std::list<_Ty,std::allocator<_Ty>>,std::allocator<std::list<_Ty,std::allocator<_Ty>>>>::_Udefault(std::list<_Ty,std::allocator<_Ty>> *,const unsigned __int64)' being compiled
1> with
1> [
1> _Ty=NonCopyable
1> ]
1>[...]testcard.cpp(37): note: see reference to class template instantiation 'std::vector<std::list<NonCopyable,std::allocator<_Ty>>,std::allocator<std::list<_Ty,std::allocator<_Ty>>>>' being compiled
1> with
1> [
1> _Ty=NonCopyable
1> ]
1>Done building project "testcore.vcxproj" -- FAILED.
========== Build: 0 succeeded, 1 failed, 2 up-to-date, 0 skipped ==========
c++ c++11 stl
add a comment |
I have a non-copyable class, simplified as follows:
struct NonCopyable
{
NonCopyable() = default;
NonCopyable(const NonCopyable&) = delete;
NonCopyable& operator = (const NonCopyable&) = delete;
NonCopyable(NonCopyable&&) = default;
NonCopyable& operator = (NonCopyable&&) = default;
};
I store the objects of this class in various std::lists. At one point I have an empty std::vector of these lists, which I would like to resize to contain a fixed number of empty lists. However, this complains about the lack of a NonCopyable copy constructor, even though (as far as I can see) it shouldn't be trying to construct any NonCopyables!
std::vector<std::list<NonCopyable>> v; // OK
v.resize(4); // ERROR
v.emplace_back(); // ERROR
std::list<NonCopyable> l; // OK
v.push_back(l); // ERROR (unsurprisingly)
v.push_back(std::move(l)); // ERROR
Why is this? Is there any way to do this without making the class copyable?
I'm using VS2017 with /std:c++17 in case that makes any difference.
Here's the full error output from just trying to resize (first two lines above).
1>------ Build started: Project: testcore, Configuration: Debug x64 ------
1>testcard.cpp
1>c:program files (x86)microsoft visual studio2017communityvctoolsmsvc14.15.26726includexmemory0(881): error C2280: 'NonCopyable::NonCopyable(const NonCopyable &)': attempting to reference a deleted function
1>[...]testcard.cpp(30): note: see declaration of 'NonCopyable::NonCopyable'
1>[...]testcard.cpp(30): note: 'NonCopyable::NonCopyable(const NonCopyable &)': function was explicitly deleted
1>c:program files (x86)microsoft visual studio2017communityvctoolsmsvc14.15.26726includelist(711): note: see reference to function template instantiation 'void std::_Default_allocator_traits<_Alloc>::construct<_Ty,const NonCopyable&>(_Alloc &,_Objty *const ,const NonCopyable &)' being compiled
1> with
1> [
1> _Alloc=std::allocator<std::_List_node<NonCopyable,std::_Default_allocator_traits<std::allocator<NonCopyable>>::void_pointer>>,
1> _Ty=NonCopyable,
1> _Objty=NonCopyable
1> ]
1>c:program files (x86)microsoft visual studio2017communityvctoolsmsvc14.15.26726includelist(716): note: see reference to function template instantiation 'void std::_Default_allocator_traits<_Alloc>::construct<_Ty,const NonCopyable&>(_Alloc &,_Objty *const ,const NonCopyable &)' being compiled
1> with
1> [
1> _Alloc=std::allocator<std::_List_node<NonCopyable,std::_Default_allocator_traits<std::allocator<NonCopyable>>::void_pointer>>,
1> _Ty=NonCopyable,
1> _Objty=NonCopyable
1> ]
1>c:program files (x86)microsoft visual studio2017communityvctoolsmsvc14.15.26726includelist(947): note: see reference to function template instantiation 'std::_List_node<_Ty,std::_Default_allocator_traits<_Alloc>::void_pointer> *std::_List_buy<_Ty,_Alloc>::_Buynode<const NonCopyable&>(std::_List_node<_Ty,std::_Default_allocator_traits<_Alloc>::void_pointer> *,std::_List_node<_Ty,std::_Default_allocator_traits<_Alloc>::void_pointer> *,const NonCopyable &)' being compiled
1> with
1> [
1> _Ty=NonCopyable,
1> _Alloc=std::allocator<NonCopyable>
1> ]
1>c:program files (x86)microsoft visual studio2017communityvctoolsmsvc14.15.26726includelist(950): note: see reference to function template instantiation 'std::_List_node<_Ty,std::_Default_allocator_traits<_Alloc>::void_pointer> *std::_List_buy<_Ty,_Alloc>::_Buynode<const NonCopyable&>(std::_List_node<_Ty,std::_Default_allocator_traits<_Alloc>::void_pointer> *,std::_List_node<_Ty,std::_Default_allocator_traits<_Alloc>::void_pointer> *,const NonCopyable &)' being compiled
1> with
1> [
1> _Ty=NonCopyable,
1> _Alloc=std::allocator<NonCopyable>
1> ]
1>c:program files (x86)microsoft visual studio2017communityvctoolsmsvc14.15.26726includelist(1308): note: see reference to function template instantiation 'void std::list<NonCopyable,std::allocator<_Ty>>::_Insert<const NonCopyable&>(std::_List_unchecked_const_iterator<std::_List_val<std::_List_simple_types<_Ty>>,std::_Iterator_base0>,const NonCopyable &)' being compiled
1> with
1> [
1> _Ty=NonCopyable
1> ]
1>c:program files (x86)microsoft visual studio2017communityvctoolsmsvc14.15.26726includelist(1308): note: see reference to function template instantiation 'void std::list<NonCopyable,std::allocator<_Ty>>::_Insert<const NonCopyable&>(std::_List_unchecked_const_iterator<std::_List_val<std::_List_simple_types<_Ty>>,std::_Iterator_base0>,const NonCopyable &)' being compiled
1> with
1> [
1> _Ty=NonCopyable
1> ]
1>c:program files (x86)microsoft visual studio2017communityvctoolsmsvc14.15.26726includelist(1265): note: see reference to function template instantiation 'void std::list<NonCopyable,std::allocator<_Ty>>::_Insert_range<_Iter>(std::_List_unchecked_const_iterator<std::_List_val<std::_List_simple_types<_Ty>>,std::_Iterator_base0>,_Iter,_Iter,std::forward_iterator_tag)' being compiled
1> with
1> [
1> _Ty=NonCopyable,
1> _Iter=std::_List_const_iterator<std::_List_val<std::_List_simple_types<NonCopyable>>>
1> ]
1>c:program files (x86)microsoft visual studio2017communityvctoolsmsvc14.15.26726includelist(1264): note: see reference to function template instantiation 'void std::list<NonCopyable,std::allocator<_Ty>>::_Insert_range<_Iter>(std::_List_unchecked_const_iterator<std::_List_val<std::_List_simple_types<_Ty>>,std::_Iterator_base0>,_Iter,_Iter,std::forward_iterator_tag)' being compiled
1> with
1> [
1> _Ty=NonCopyable,
1> _Iter=std::_List_const_iterator<std::_List_val<std::_List_simple_types<NonCopyable>>>
1> ]
1>c:program files (x86)microsoft visual studio2017communityvctoolsmsvc14.15.26726includelist(800): note: see reference to function template instantiation 'std::_List_iterator<std::_List_val<std::_List_simple_types<_Ty>>> std::list<_Ty,std::allocator<_Ty>>::insert<std::_List_const_iterator<std::_List_val<std::_List_simple_types<_Ty>>>,void>(std::_List_const_iterator<std::_List_val<std::_List_simple_types<_Ty>>>,_Iter,_Iter)' being compiled
1> with
1> [
1> _Ty=NonCopyable,
1> _Iter=std::_List_const_iterator<std::_List_val<std::_List_simple_types<NonCopyable>>>
1> ]
1>c:program files (x86)microsoft visual studio2017communityvctoolsmsvc14.15.26726includelist(800): note: see reference to function template instantiation 'std::_List_iterator<std::_List_val<std::_List_simple_types<_Ty>>> std::list<_Ty,std::allocator<_Ty>>::insert<std::_List_const_iterator<std::_List_val<std::_List_simple_types<_Ty>>>,void>(std::_List_const_iterator<std::_List_val<std::_List_simple_types<_Ty>>>,_Iter,_Iter)' being compiled
1> with
1> [
1> _Ty=NonCopyable,
1> _Iter=std::_List_const_iterator<std::_List_val<std::_List_simple_types<NonCopyable>>>
1> ]
1>c:program files (x86)microsoft visual studio2017communityvctoolsmsvc14.15.26726includelist(796): note: while compiling class template member function 'std::list<NonCopyable,std::allocator<_Ty>>::list(const std::list<_Ty,std::allocator<_Ty>> &)'
1> with
1> [
1> _Ty=NonCopyable
1> ]
1>c:program files (x86)microsoft visual studio2017communityvctoolsmsvc14.15.26726includexmemory0(881): note: see reference to function template instantiation 'std::list<NonCopyable,std::allocator<_Ty>>::list(const std::list<_Ty,std::allocator<_Ty>> &)' being compiled
1> with
1> [
1> _Ty=NonCopyable
1> ]
1>c:program files (x86)microsoft visual studio2017communityvctoolsmsvc14.15.26726includevector(1812): note: see reference to class template instantiation 'std::list<NonCopyable,std::allocator<_Ty>>' being compiled
1> with
1> [
1> _Ty=NonCopyable
1> ]
1>c:program files (x86)microsoft visual studio2017communityvctoolsmsvc14.15.26726includevector(1811): note: while compiling class template member function 'std::list<NonCopyable,std::allocator<_Ty>> *std::vector<std::list<_Ty,std::allocator<_Ty>>,std::allocator<std::list<_Ty,std::allocator<_Ty>>>>::_Udefault(std::list<_Ty,std::allocator<_Ty>> *,const unsigned __int64)'
1> with
1> [
1> _Ty=NonCopyable
1> ]
1>c:program files (x86)microsoft visual studio2017communityvctoolsmsvc14.15.26726includevector(1479): note: see reference to function template instantiation 'std::list<NonCopyable,std::allocator<_Ty>> *std::vector<std::list<_Ty,std::allocator<_Ty>>,std::allocator<std::list<_Ty,std::allocator<_Ty>>>>::_Udefault(std::list<_Ty,std::allocator<_Ty>> *,const unsigned __int64)' being compiled
1> with
1> [
1> _Ty=NonCopyable
1> ]
1>[...]testcard.cpp(37): note: see reference to class template instantiation 'std::vector<std::list<NonCopyable,std::allocator<_Ty>>,std::allocator<std::list<_Ty,std::allocator<_Ty>>>>' being compiled
1> with
1> [
1> _Ty=NonCopyable
1> ]
1>Done building project "testcore.vcxproj" -- FAILED.
========== Build: 0 succeeded, 1 failed, 2 up-to-date, 0 skipped ==========
c++ c++11 stl
add a comment |
I have a non-copyable class, simplified as follows:
struct NonCopyable
{
NonCopyable() = default;
NonCopyable(const NonCopyable&) = delete;
NonCopyable& operator = (const NonCopyable&) = delete;
NonCopyable(NonCopyable&&) = default;
NonCopyable& operator = (NonCopyable&&) = default;
};
I store the objects of this class in various std::lists. At one point I have an empty std::vector of these lists, which I would like to resize to contain a fixed number of empty lists. However, this complains about the lack of a NonCopyable copy constructor, even though (as far as I can see) it shouldn't be trying to construct any NonCopyables!
std::vector<std::list<NonCopyable>> v; // OK
v.resize(4); // ERROR
v.emplace_back(); // ERROR
std::list<NonCopyable> l; // OK
v.push_back(l); // ERROR (unsurprisingly)
v.push_back(std::move(l)); // ERROR
Why is this? Is there any way to do this without making the class copyable?
I'm using VS2017 with /std:c++17 in case that makes any difference.
Here's the full error output from just trying to resize (first two lines above).
1>------ Build started: Project: testcore, Configuration: Debug x64 ------
1>testcard.cpp
1>c:program files (x86)microsoft visual studio2017communityvctoolsmsvc14.15.26726includexmemory0(881): error C2280: 'NonCopyable::NonCopyable(const NonCopyable &)': attempting to reference a deleted function
1>[...]testcard.cpp(30): note: see declaration of 'NonCopyable::NonCopyable'
1>[...]testcard.cpp(30): note: 'NonCopyable::NonCopyable(const NonCopyable &)': function was explicitly deleted
1>c:program files (x86)microsoft visual studio2017communityvctoolsmsvc14.15.26726includelist(711): note: see reference to function template instantiation 'void std::_Default_allocator_traits<_Alloc>::construct<_Ty,const NonCopyable&>(_Alloc &,_Objty *const ,const NonCopyable &)' being compiled
1> with
1> [
1> _Alloc=std::allocator<std::_List_node<NonCopyable,std::_Default_allocator_traits<std::allocator<NonCopyable>>::void_pointer>>,
1> _Ty=NonCopyable,
1> _Objty=NonCopyable
1> ]
1>c:program files (x86)microsoft visual studio2017communityvctoolsmsvc14.15.26726includelist(716): note: see reference to function template instantiation 'void std::_Default_allocator_traits<_Alloc>::construct<_Ty,const NonCopyable&>(_Alloc &,_Objty *const ,const NonCopyable &)' being compiled
1> with
1> [
1> _Alloc=std::allocator<std::_List_node<NonCopyable,std::_Default_allocator_traits<std::allocator<NonCopyable>>::void_pointer>>,
1> _Ty=NonCopyable,
1> _Objty=NonCopyable
1> ]
1>c:program files (x86)microsoft visual studio2017communityvctoolsmsvc14.15.26726includelist(947): note: see reference to function template instantiation 'std::_List_node<_Ty,std::_Default_allocator_traits<_Alloc>::void_pointer> *std::_List_buy<_Ty,_Alloc>::_Buynode<const NonCopyable&>(std::_List_node<_Ty,std::_Default_allocator_traits<_Alloc>::void_pointer> *,std::_List_node<_Ty,std::_Default_allocator_traits<_Alloc>::void_pointer> *,const NonCopyable &)' being compiled
1> with
1> [
1> _Ty=NonCopyable,
1> _Alloc=std::allocator<NonCopyable>
1> ]
1>c:program files (x86)microsoft visual studio2017communityvctoolsmsvc14.15.26726includelist(950): note: see reference to function template instantiation 'std::_List_node<_Ty,std::_Default_allocator_traits<_Alloc>::void_pointer> *std::_List_buy<_Ty,_Alloc>::_Buynode<const NonCopyable&>(std::_List_node<_Ty,std::_Default_allocator_traits<_Alloc>::void_pointer> *,std::_List_node<_Ty,std::_Default_allocator_traits<_Alloc>::void_pointer> *,const NonCopyable &)' being compiled
1> with
1> [
1> _Ty=NonCopyable,
1> _Alloc=std::allocator<NonCopyable>
1> ]
1>c:program files (x86)microsoft visual studio2017communityvctoolsmsvc14.15.26726includelist(1308): note: see reference to function template instantiation 'void std::list<NonCopyable,std::allocator<_Ty>>::_Insert<const NonCopyable&>(std::_List_unchecked_const_iterator<std::_List_val<std::_List_simple_types<_Ty>>,std::_Iterator_base0>,const NonCopyable &)' being compiled
1> with
1> [
1> _Ty=NonCopyable
1> ]
1>c:program files (x86)microsoft visual studio2017communityvctoolsmsvc14.15.26726includelist(1308): note: see reference to function template instantiation 'void std::list<NonCopyable,std::allocator<_Ty>>::_Insert<const NonCopyable&>(std::_List_unchecked_const_iterator<std::_List_val<std::_List_simple_types<_Ty>>,std::_Iterator_base0>,const NonCopyable &)' being compiled
1> with
1> [
1> _Ty=NonCopyable
1> ]
1>c:program files (x86)microsoft visual studio2017communityvctoolsmsvc14.15.26726includelist(1265): note: see reference to function template instantiation 'void std::list<NonCopyable,std::allocator<_Ty>>::_Insert_range<_Iter>(std::_List_unchecked_const_iterator<std::_List_val<std::_List_simple_types<_Ty>>,std::_Iterator_base0>,_Iter,_Iter,std::forward_iterator_tag)' being compiled
1> with
1> [
1> _Ty=NonCopyable,
1> _Iter=std::_List_const_iterator<std::_List_val<std::_List_simple_types<NonCopyable>>>
1> ]
1>c:program files (x86)microsoft visual studio2017communityvctoolsmsvc14.15.26726includelist(1264): note: see reference to function template instantiation 'void std::list<NonCopyable,std::allocator<_Ty>>::_Insert_range<_Iter>(std::_List_unchecked_const_iterator<std::_List_val<std::_List_simple_types<_Ty>>,std::_Iterator_base0>,_Iter,_Iter,std::forward_iterator_tag)' being compiled
1> with
1> [
1> _Ty=NonCopyable,
1> _Iter=std::_List_const_iterator<std::_List_val<std::_List_simple_types<NonCopyable>>>
1> ]
1>c:program files (x86)microsoft visual studio2017communityvctoolsmsvc14.15.26726includelist(800): note: see reference to function template instantiation 'std::_List_iterator<std::_List_val<std::_List_simple_types<_Ty>>> std::list<_Ty,std::allocator<_Ty>>::insert<std::_List_const_iterator<std::_List_val<std::_List_simple_types<_Ty>>>,void>(std::_List_const_iterator<std::_List_val<std::_List_simple_types<_Ty>>>,_Iter,_Iter)' being compiled
1> with
1> [
1> _Ty=NonCopyable,
1> _Iter=std::_List_const_iterator<std::_List_val<std::_List_simple_types<NonCopyable>>>
1> ]
1>c:program files (x86)microsoft visual studio2017communityvctoolsmsvc14.15.26726includelist(800): note: see reference to function template instantiation 'std::_List_iterator<std::_List_val<std::_List_simple_types<_Ty>>> std::list<_Ty,std::allocator<_Ty>>::insert<std::_List_const_iterator<std::_List_val<std::_List_simple_types<_Ty>>>,void>(std::_List_const_iterator<std::_List_val<std::_List_simple_types<_Ty>>>,_Iter,_Iter)' being compiled
1> with
1> [
1> _Ty=NonCopyable,
1> _Iter=std::_List_const_iterator<std::_List_val<std::_List_simple_types<NonCopyable>>>
1> ]
1>c:program files (x86)microsoft visual studio2017communityvctoolsmsvc14.15.26726includelist(796): note: while compiling class template member function 'std::list<NonCopyable,std::allocator<_Ty>>::list(const std::list<_Ty,std::allocator<_Ty>> &)'
1> with
1> [
1> _Ty=NonCopyable
1> ]
1>c:program files (x86)microsoft visual studio2017communityvctoolsmsvc14.15.26726includexmemory0(881): note: see reference to function template instantiation 'std::list<NonCopyable,std::allocator<_Ty>>::list(const std::list<_Ty,std::allocator<_Ty>> &)' being compiled
1> with
1> [
1> _Ty=NonCopyable
1> ]
1>c:program files (x86)microsoft visual studio2017communityvctoolsmsvc14.15.26726includevector(1812): note: see reference to class template instantiation 'std::list<NonCopyable,std::allocator<_Ty>>' being compiled
1> with
1> [
1> _Ty=NonCopyable
1> ]
1>c:program files (x86)microsoft visual studio2017communityvctoolsmsvc14.15.26726includevector(1811): note: while compiling class template member function 'std::list<NonCopyable,std::allocator<_Ty>> *std::vector<std::list<_Ty,std::allocator<_Ty>>,std::allocator<std::list<_Ty,std::allocator<_Ty>>>>::_Udefault(std::list<_Ty,std::allocator<_Ty>> *,const unsigned __int64)'
1> with
1> [
1> _Ty=NonCopyable
1> ]
1>c:program files (x86)microsoft visual studio2017communityvctoolsmsvc14.15.26726includevector(1479): note: see reference to function template instantiation 'std::list<NonCopyable,std::allocator<_Ty>> *std::vector<std::list<_Ty,std::allocator<_Ty>>,std::allocator<std::list<_Ty,std::allocator<_Ty>>>>::_Udefault(std::list<_Ty,std::allocator<_Ty>> *,const unsigned __int64)' being compiled
1> with
1> [
1> _Ty=NonCopyable
1> ]
1>[...]testcard.cpp(37): note: see reference to class template instantiation 'std::vector<std::list<NonCopyable,std::allocator<_Ty>>,std::allocator<std::list<_Ty,std::allocator<_Ty>>>>' being compiled
1> with
1> [
1> _Ty=NonCopyable
1> ]
1>Done building project "testcore.vcxproj" -- FAILED.
========== Build: 0 succeeded, 1 failed, 2 up-to-date, 0 skipped ==========
c++ c++11 stl
I have a non-copyable class, simplified as follows:
struct NonCopyable
{
NonCopyable() = default;
NonCopyable(const NonCopyable&) = delete;
NonCopyable& operator = (const NonCopyable&) = delete;
NonCopyable(NonCopyable&&) = default;
NonCopyable& operator = (NonCopyable&&) = default;
};
I store the objects of this class in various std::lists. At one point I have an empty std::vector of these lists, which I would like to resize to contain a fixed number of empty lists. However, this complains about the lack of a NonCopyable copy constructor, even though (as far as I can see) it shouldn't be trying to construct any NonCopyables!
std::vector<std::list<NonCopyable>> v; // OK
v.resize(4); // ERROR
v.emplace_back(); // ERROR
std::list<NonCopyable> l; // OK
v.push_back(l); // ERROR (unsurprisingly)
v.push_back(std::move(l)); // ERROR
Why is this? Is there any way to do this without making the class copyable?
I'm using VS2017 with /std:c++17 in case that makes any difference.
Here's the full error output from just trying to resize (first two lines above).
1>------ Build started: Project: testcore, Configuration: Debug x64 ------
1>testcard.cpp
1>c:program files (x86)microsoft visual studio2017communityvctoolsmsvc14.15.26726includexmemory0(881): error C2280: 'NonCopyable::NonCopyable(const NonCopyable &)': attempting to reference a deleted function
1>[...]testcard.cpp(30): note: see declaration of 'NonCopyable::NonCopyable'
1>[...]testcard.cpp(30): note: 'NonCopyable::NonCopyable(const NonCopyable &)': function was explicitly deleted
1>c:program files (x86)microsoft visual studio2017communityvctoolsmsvc14.15.26726includelist(711): note: see reference to function template instantiation 'void std::_Default_allocator_traits<_Alloc>::construct<_Ty,const NonCopyable&>(_Alloc &,_Objty *const ,const NonCopyable &)' being compiled
1> with
1> [
1> _Alloc=std::allocator<std::_List_node<NonCopyable,std::_Default_allocator_traits<std::allocator<NonCopyable>>::void_pointer>>,
1> _Ty=NonCopyable,
1> _Objty=NonCopyable
1> ]
1>c:program files (x86)microsoft visual studio2017communityvctoolsmsvc14.15.26726includelist(716): note: see reference to function template instantiation 'void std::_Default_allocator_traits<_Alloc>::construct<_Ty,const NonCopyable&>(_Alloc &,_Objty *const ,const NonCopyable &)' being compiled
1> with
1> [
1> _Alloc=std::allocator<std::_List_node<NonCopyable,std::_Default_allocator_traits<std::allocator<NonCopyable>>::void_pointer>>,
1> _Ty=NonCopyable,
1> _Objty=NonCopyable
1> ]
1>c:program files (x86)microsoft visual studio2017communityvctoolsmsvc14.15.26726includelist(947): note: see reference to function template instantiation 'std::_List_node<_Ty,std::_Default_allocator_traits<_Alloc>::void_pointer> *std::_List_buy<_Ty,_Alloc>::_Buynode<const NonCopyable&>(std::_List_node<_Ty,std::_Default_allocator_traits<_Alloc>::void_pointer> *,std::_List_node<_Ty,std::_Default_allocator_traits<_Alloc>::void_pointer> *,const NonCopyable &)' being compiled
1> with
1> [
1> _Ty=NonCopyable,
1> _Alloc=std::allocator<NonCopyable>
1> ]
1>c:program files (x86)microsoft visual studio2017communityvctoolsmsvc14.15.26726includelist(950): note: see reference to function template instantiation 'std::_List_node<_Ty,std::_Default_allocator_traits<_Alloc>::void_pointer> *std::_List_buy<_Ty,_Alloc>::_Buynode<const NonCopyable&>(std::_List_node<_Ty,std::_Default_allocator_traits<_Alloc>::void_pointer> *,std::_List_node<_Ty,std::_Default_allocator_traits<_Alloc>::void_pointer> *,const NonCopyable &)' being compiled
1> with
1> [
1> _Ty=NonCopyable,
1> _Alloc=std::allocator<NonCopyable>
1> ]
1>c:program files (x86)microsoft visual studio2017communityvctoolsmsvc14.15.26726includelist(1308): note: see reference to function template instantiation 'void std::list<NonCopyable,std::allocator<_Ty>>::_Insert<const NonCopyable&>(std::_List_unchecked_const_iterator<std::_List_val<std::_List_simple_types<_Ty>>,std::_Iterator_base0>,const NonCopyable &)' being compiled
1> with
1> [
1> _Ty=NonCopyable
1> ]
1>c:program files (x86)microsoft visual studio2017communityvctoolsmsvc14.15.26726includelist(1308): note: see reference to function template instantiation 'void std::list<NonCopyable,std::allocator<_Ty>>::_Insert<const NonCopyable&>(std::_List_unchecked_const_iterator<std::_List_val<std::_List_simple_types<_Ty>>,std::_Iterator_base0>,const NonCopyable &)' being compiled
1> with
1> [
1> _Ty=NonCopyable
1> ]
1>c:program files (x86)microsoft visual studio2017communityvctoolsmsvc14.15.26726includelist(1265): note: see reference to function template instantiation 'void std::list<NonCopyable,std::allocator<_Ty>>::_Insert_range<_Iter>(std::_List_unchecked_const_iterator<std::_List_val<std::_List_simple_types<_Ty>>,std::_Iterator_base0>,_Iter,_Iter,std::forward_iterator_tag)' being compiled
1> with
1> [
1> _Ty=NonCopyable,
1> _Iter=std::_List_const_iterator<std::_List_val<std::_List_simple_types<NonCopyable>>>
1> ]
1>c:program files (x86)microsoft visual studio2017communityvctoolsmsvc14.15.26726includelist(1264): note: see reference to function template instantiation 'void std::list<NonCopyable,std::allocator<_Ty>>::_Insert_range<_Iter>(std::_List_unchecked_const_iterator<std::_List_val<std::_List_simple_types<_Ty>>,std::_Iterator_base0>,_Iter,_Iter,std::forward_iterator_tag)' being compiled
1> with
1> [
1> _Ty=NonCopyable,
1> _Iter=std::_List_const_iterator<std::_List_val<std::_List_simple_types<NonCopyable>>>
1> ]
1>c:program files (x86)microsoft visual studio2017communityvctoolsmsvc14.15.26726includelist(800): note: see reference to function template instantiation 'std::_List_iterator<std::_List_val<std::_List_simple_types<_Ty>>> std::list<_Ty,std::allocator<_Ty>>::insert<std::_List_const_iterator<std::_List_val<std::_List_simple_types<_Ty>>>,void>(std::_List_const_iterator<std::_List_val<std::_List_simple_types<_Ty>>>,_Iter,_Iter)' being compiled
1> with
1> [
1> _Ty=NonCopyable,
1> _Iter=std::_List_const_iterator<std::_List_val<std::_List_simple_types<NonCopyable>>>
1> ]
1>c:program files (x86)microsoft visual studio2017communityvctoolsmsvc14.15.26726includelist(800): note: see reference to function template instantiation 'std::_List_iterator<std::_List_val<std::_List_simple_types<_Ty>>> std::list<_Ty,std::allocator<_Ty>>::insert<std::_List_const_iterator<std::_List_val<std::_List_simple_types<_Ty>>>,void>(std::_List_const_iterator<std::_List_val<std::_List_simple_types<_Ty>>>,_Iter,_Iter)' being compiled
1> with
1> [
1> _Ty=NonCopyable,
1> _Iter=std::_List_const_iterator<std::_List_val<std::_List_simple_types<NonCopyable>>>
1> ]
1>c:program files (x86)microsoft visual studio2017communityvctoolsmsvc14.15.26726includelist(796): note: while compiling class template member function 'std::list<NonCopyable,std::allocator<_Ty>>::list(const std::list<_Ty,std::allocator<_Ty>> &)'
1> with
1> [
1> _Ty=NonCopyable
1> ]
1>c:program files (x86)microsoft visual studio2017communityvctoolsmsvc14.15.26726includexmemory0(881): note: see reference to function template instantiation 'std::list<NonCopyable,std::allocator<_Ty>>::list(const std::list<_Ty,std::allocator<_Ty>> &)' being compiled
1> with
1> [
1> _Ty=NonCopyable
1> ]
1>c:program files (x86)microsoft visual studio2017communityvctoolsmsvc14.15.26726includevector(1812): note: see reference to class template instantiation 'std::list<NonCopyable,std::allocator<_Ty>>' being compiled
1> with
1> [
1> _Ty=NonCopyable
1> ]
1>c:program files (x86)microsoft visual studio2017communityvctoolsmsvc14.15.26726includevector(1811): note: while compiling class template member function 'std::list<NonCopyable,std::allocator<_Ty>> *std::vector<std::list<_Ty,std::allocator<_Ty>>,std::allocator<std::list<_Ty,std::allocator<_Ty>>>>::_Udefault(std::list<_Ty,std::allocator<_Ty>> *,const unsigned __int64)'
1> with
1> [
1> _Ty=NonCopyable
1> ]
1>c:program files (x86)microsoft visual studio2017communityvctoolsmsvc14.15.26726includevector(1479): note: see reference to function template instantiation 'std::list<NonCopyable,std::allocator<_Ty>> *std::vector<std::list<_Ty,std::allocator<_Ty>>,std::allocator<std::list<_Ty,std::allocator<_Ty>>>>::_Udefault(std::list<_Ty,std::allocator<_Ty>> *,const unsigned __int64)' being compiled
1> with
1> [
1> _Ty=NonCopyable
1> ]
1>[...]testcard.cpp(37): note: see reference to class template instantiation 'std::vector<std::list<NonCopyable,std::allocator<_Ty>>,std::allocator<std::list<_Ty,std::allocator<_Ty>>>>' being compiled
1> with
1> [
1> _Ty=NonCopyable
1> ]
1>Done building project "testcore.vcxproj" -- FAILED.
========== Build: 0 succeeded, 1 failed, 2 up-to-date, 0 skipped ==========
c++ c++11 stl
c++ c++11 stl
edited Nov 22 at 14:11
asked Nov 22 at 13:25
Uri Zarfaty
733515
733515
add a comment |
add a comment |
2 Answers
2
active
oldest
votes
std::list
is not noexcept-movable, but is copyable. Therefore, std::vector
prefers list
's the copy-constructor over its move-constructor, regardless.
To work around the issue, you have to wrap your std::list
in a class that is not copyable.
Thanks. What if the NonCopyable class was also not movable? (Moving objects between lists would still be possible I believe, since it doesn't invalidate references,)
– Uri Zarfaty
Nov 22 at 15:02
1
@UriZarfaty It would be possible to move the list's nodes around usingsplice
, butstd::vector
does not know about it.
– j6t
Nov 22 at 15:04
1
@StoryTeller It is not exactly QoI, but a matter of following the Standard literally. I do not see anoexcept
specification on the move constructor in the list synopsis. That said, I agree that the Clang's and GCC's behavior is preferable.
– j6t
Nov 22 at 15:42
1
@j6t - The standard has a debatable QoI too. Well, quality of specification would be more exact, but the point still holds.
– StoryTeller
Nov 22 at 15:58
1
TheseRequires
clauses are directives for the programmer, not the compiler. If the conditions are violated, you get what you deserve; at best it does not compile, at worst it is undefined behavior.
– j6t
Nov 23 at 10:13
|
show 10 more comments
As @j6t pointed out, it seems it can't be done. A vector with a std::list
with non-copyable elements can not be expanded according to the standard (...). If it was my private project I'd actually consider something like this:
#include <iostream>
#include <vector>
#include <list>
namespace xxx {
// <flame_bait>
template<class T, class Enable = void>
struct list : std::list<T> {
list() : std::list<T>() {}
list(list&&) = default;
list& operator=(list&&) = default;
list(const list&) = delete;
list& operator=(const list&) = delete;
};
template<class T>
struct list<T, typename std::enable_if<std::is_copy_constructible<T>::value>::type> : std::list<T> {};
// </flame_bait>
}
struct NonCopyable
{
int m_id;
NonCopyable(int id = 0) : m_id(id) {}
NonCopyable(const NonCopyable&) = delete;
NonCopyable& operator = (const NonCopyable&) = delete;
NonCopyable(NonCopyable&&) noexcept = default;
NonCopyable& operator = (NonCopyable&&) noexcept = default;
~NonCopyable() = default;
friend std::ostream& operator<<(std::ostream&, const NonCopyable&);
};
std::ostream& operator<<(std::ostream& os, const NonCopyable& nc) {
os << "I am not a free man, I am number " << nc.m_id;
return os;
}
int main() {
std::vector<xxx::list<NonCopyable>> v;
v.resize(4); // now working
int id = 0;
for (auto& l : v) {
l.emplace_back(++id); // emplace_back one NonCopyable per list
}
xxx::list<NonCopyable> li; // Create a separate list
li.emplace_back(++id); // create one...
v.emplace_back(std::move(li)); // and move list to vector is now working
for (auto& l : v) {
for (auto& nc : l) {
std::cout << nc << "n";
}
}
}
Expected output:
I am not a free man, I am number 1
I am not a free man, I am number 2
I am not a free man, I am number 3
I am not a free man, I am number 4
I am not a free man, I am number 5
Seems I missed the part wherev.resize(4);
fails. What's the error message from that line?
– Ted Lyngmo
Nov 22 at 13:59
1
error C2280: 'NonCopyable::NonCopyable(const NonCopyable &)': attempting to reference a deleted function
. I've added the full error output for that to the post.
– Uri Zarfaty
Nov 22 at 14:11
1
Great! How odd though ... :-) I'll give it a try in VS when I get home.
– Ted Lyngmo
Nov 22 at 14:14
Just to make it worse:v.reserve(4);
gives the same error.
– Ted Lyngmo
Nov 22 at 15:20
1
I added axxx::list
replacement forstd::list
that hopefully should work as a container for both copyable and non-copyable objects. I''m terrible with templates though so be aware ...
– Ted Lyngmo
Nov 22 at 17:47
add a comment |
Your Answer
StackExchange.ifUsing("editor", function () {
StackExchange.using("externalEditor", function () {
StackExchange.using("snippets", function () {
StackExchange.snippets.init();
});
});
}, "code-snippets");
StackExchange.ready(function() {
var channelOptions = {
tags: "".split(" "),
id: "1"
};
initTagRenderer("".split(" "), "".split(" "), channelOptions);
StackExchange.using("externalEditor", function() {
// Have to fire editor after snippets, if snippets enabled
if (StackExchange.settings.snippets.snippetsEnabled) {
StackExchange.using("snippets", function() {
createEditor();
});
}
else {
createEditor();
}
});
function createEditor() {
StackExchange.prepareEditor({
heartbeatType: 'answer',
autoActivateHeartbeat: false,
convertImagesToLinks: true,
noModals: true,
showLowRepImageUploadWarning: true,
reputationToPostImages: 10,
bindNavPrevention: true,
postfix: "",
imageUploader: {
brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
allowUrls: true
},
onDemand: true,
discardSelector: ".discard-answer"
,immediatelyShowMarkdownHelp:true
});
}
});
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53432012%2fnon-copyable-elements-in-a-stdvector-of-stdlists%23new-answer', 'question_page');
}
);
Post as a guest
Required, but never shown
2 Answers
2
active
oldest
votes
2 Answers
2
active
oldest
votes
active
oldest
votes
active
oldest
votes
std::list
is not noexcept-movable, but is copyable. Therefore, std::vector
prefers list
's the copy-constructor over its move-constructor, regardless.
To work around the issue, you have to wrap your std::list
in a class that is not copyable.
Thanks. What if the NonCopyable class was also not movable? (Moving objects between lists would still be possible I believe, since it doesn't invalidate references,)
– Uri Zarfaty
Nov 22 at 15:02
1
@UriZarfaty It would be possible to move the list's nodes around usingsplice
, butstd::vector
does not know about it.
– j6t
Nov 22 at 15:04
1
@StoryTeller It is not exactly QoI, but a matter of following the Standard literally. I do not see anoexcept
specification on the move constructor in the list synopsis. That said, I agree that the Clang's and GCC's behavior is preferable.
– j6t
Nov 22 at 15:42
1
@j6t - The standard has a debatable QoI too. Well, quality of specification would be more exact, but the point still holds.
– StoryTeller
Nov 22 at 15:58
1
TheseRequires
clauses are directives for the programmer, not the compiler. If the conditions are violated, you get what you deserve; at best it does not compile, at worst it is undefined behavior.
– j6t
Nov 23 at 10:13
|
show 10 more comments
std::list
is not noexcept-movable, but is copyable. Therefore, std::vector
prefers list
's the copy-constructor over its move-constructor, regardless.
To work around the issue, you have to wrap your std::list
in a class that is not copyable.
Thanks. What if the NonCopyable class was also not movable? (Moving objects between lists would still be possible I believe, since it doesn't invalidate references,)
– Uri Zarfaty
Nov 22 at 15:02
1
@UriZarfaty It would be possible to move the list's nodes around usingsplice
, butstd::vector
does not know about it.
– j6t
Nov 22 at 15:04
1
@StoryTeller It is not exactly QoI, but a matter of following the Standard literally. I do not see anoexcept
specification on the move constructor in the list synopsis. That said, I agree that the Clang's and GCC's behavior is preferable.
– j6t
Nov 22 at 15:42
1
@j6t - The standard has a debatable QoI too. Well, quality of specification would be more exact, but the point still holds.
– StoryTeller
Nov 22 at 15:58
1
TheseRequires
clauses are directives for the programmer, not the compiler. If the conditions are violated, you get what you deserve; at best it does not compile, at worst it is undefined behavior.
– j6t
Nov 23 at 10:13
|
show 10 more comments
std::list
is not noexcept-movable, but is copyable. Therefore, std::vector
prefers list
's the copy-constructor over its move-constructor, regardless.
To work around the issue, you have to wrap your std::list
in a class that is not copyable.
std::list
is not noexcept-movable, but is copyable. Therefore, std::vector
prefers list
's the copy-constructor over its move-constructor, regardless.
To work around the issue, you have to wrap your std::list
in a class that is not copyable.
edited Nov 22 at 14:50
answered Nov 22 at 14:44
j6t
1,171138
1,171138
Thanks. What if the NonCopyable class was also not movable? (Moving objects between lists would still be possible I believe, since it doesn't invalidate references,)
– Uri Zarfaty
Nov 22 at 15:02
1
@UriZarfaty It would be possible to move the list's nodes around usingsplice
, butstd::vector
does not know about it.
– j6t
Nov 22 at 15:04
1
@StoryTeller It is not exactly QoI, but a matter of following the Standard literally. I do not see anoexcept
specification on the move constructor in the list synopsis. That said, I agree that the Clang's and GCC's behavior is preferable.
– j6t
Nov 22 at 15:42
1
@j6t - The standard has a debatable QoI too. Well, quality of specification would be more exact, but the point still holds.
– StoryTeller
Nov 22 at 15:58
1
TheseRequires
clauses are directives for the programmer, not the compiler. If the conditions are violated, you get what you deserve; at best it does not compile, at worst it is undefined behavior.
– j6t
Nov 23 at 10:13
|
show 10 more comments
Thanks. What if the NonCopyable class was also not movable? (Moving objects between lists would still be possible I believe, since it doesn't invalidate references,)
– Uri Zarfaty
Nov 22 at 15:02
1
@UriZarfaty It would be possible to move the list's nodes around usingsplice
, butstd::vector
does not know about it.
– j6t
Nov 22 at 15:04
1
@StoryTeller It is not exactly QoI, but a matter of following the Standard literally. I do not see anoexcept
specification on the move constructor in the list synopsis. That said, I agree that the Clang's and GCC's behavior is preferable.
– j6t
Nov 22 at 15:42
1
@j6t - The standard has a debatable QoI too. Well, quality of specification would be more exact, but the point still holds.
– StoryTeller
Nov 22 at 15:58
1
TheseRequires
clauses are directives for the programmer, not the compiler. If the conditions are violated, you get what you deserve; at best it does not compile, at worst it is undefined behavior.
– j6t
Nov 23 at 10:13
Thanks. What if the NonCopyable class was also not movable? (Moving objects between lists would still be possible I believe, since it doesn't invalidate references,)
– Uri Zarfaty
Nov 22 at 15:02
Thanks. What if the NonCopyable class was also not movable? (Moving objects between lists would still be possible I believe, since it doesn't invalidate references,)
– Uri Zarfaty
Nov 22 at 15:02
1
1
@UriZarfaty It would be possible to move the list's nodes around using
splice
, but std::vector
does not know about it.– j6t
Nov 22 at 15:04
@UriZarfaty It would be possible to move the list's nodes around using
splice
, but std::vector
does not know about it.– j6t
Nov 22 at 15:04
1
1
@StoryTeller It is not exactly QoI, but a matter of following the Standard literally. I do not see a
noexcept
specification on the move constructor in the list synopsis. That said, I agree that the Clang's and GCC's behavior is preferable.– j6t
Nov 22 at 15:42
@StoryTeller It is not exactly QoI, but a matter of following the Standard literally. I do not see a
noexcept
specification on the move constructor in the list synopsis. That said, I agree that the Clang's and GCC's behavior is preferable.– j6t
Nov 22 at 15:42
1
1
@j6t - The standard has a debatable QoI too. Well, quality of specification would be more exact, but the point still holds.
– StoryTeller
Nov 22 at 15:58
@j6t - The standard has a debatable QoI too. Well, quality of specification would be more exact, but the point still holds.
– StoryTeller
Nov 22 at 15:58
1
1
These
Requires
clauses are directives for the programmer, not the compiler. If the conditions are violated, you get what you deserve; at best it does not compile, at worst it is undefined behavior.– j6t
Nov 23 at 10:13
These
Requires
clauses are directives for the programmer, not the compiler. If the conditions are violated, you get what you deserve; at best it does not compile, at worst it is undefined behavior.– j6t
Nov 23 at 10:13
|
show 10 more comments
As @j6t pointed out, it seems it can't be done. A vector with a std::list
with non-copyable elements can not be expanded according to the standard (...). If it was my private project I'd actually consider something like this:
#include <iostream>
#include <vector>
#include <list>
namespace xxx {
// <flame_bait>
template<class T, class Enable = void>
struct list : std::list<T> {
list() : std::list<T>() {}
list(list&&) = default;
list& operator=(list&&) = default;
list(const list&) = delete;
list& operator=(const list&) = delete;
};
template<class T>
struct list<T, typename std::enable_if<std::is_copy_constructible<T>::value>::type> : std::list<T> {};
// </flame_bait>
}
struct NonCopyable
{
int m_id;
NonCopyable(int id = 0) : m_id(id) {}
NonCopyable(const NonCopyable&) = delete;
NonCopyable& operator = (const NonCopyable&) = delete;
NonCopyable(NonCopyable&&) noexcept = default;
NonCopyable& operator = (NonCopyable&&) noexcept = default;
~NonCopyable() = default;
friend std::ostream& operator<<(std::ostream&, const NonCopyable&);
};
std::ostream& operator<<(std::ostream& os, const NonCopyable& nc) {
os << "I am not a free man, I am number " << nc.m_id;
return os;
}
int main() {
std::vector<xxx::list<NonCopyable>> v;
v.resize(4); // now working
int id = 0;
for (auto& l : v) {
l.emplace_back(++id); // emplace_back one NonCopyable per list
}
xxx::list<NonCopyable> li; // Create a separate list
li.emplace_back(++id); // create one...
v.emplace_back(std::move(li)); // and move list to vector is now working
for (auto& l : v) {
for (auto& nc : l) {
std::cout << nc << "n";
}
}
}
Expected output:
I am not a free man, I am number 1
I am not a free man, I am number 2
I am not a free man, I am number 3
I am not a free man, I am number 4
I am not a free man, I am number 5
Seems I missed the part wherev.resize(4);
fails. What's the error message from that line?
– Ted Lyngmo
Nov 22 at 13:59
1
error C2280: 'NonCopyable::NonCopyable(const NonCopyable &)': attempting to reference a deleted function
. I've added the full error output for that to the post.
– Uri Zarfaty
Nov 22 at 14:11
1
Great! How odd though ... :-) I'll give it a try in VS when I get home.
– Ted Lyngmo
Nov 22 at 14:14
Just to make it worse:v.reserve(4);
gives the same error.
– Ted Lyngmo
Nov 22 at 15:20
1
I added axxx::list
replacement forstd::list
that hopefully should work as a container for both copyable and non-copyable objects. I''m terrible with templates though so be aware ...
– Ted Lyngmo
Nov 22 at 17:47
add a comment |
As @j6t pointed out, it seems it can't be done. A vector with a std::list
with non-copyable elements can not be expanded according to the standard (...). If it was my private project I'd actually consider something like this:
#include <iostream>
#include <vector>
#include <list>
namespace xxx {
// <flame_bait>
template<class T, class Enable = void>
struct list : std::list<T> {
list() : std::list<T>() {}
list(list&&) = default;
list& operator=(list&&) = default;
list(const list&) = delete;
list& operator=(const list&) = delete;
};
template<class T>
struct list<T, typename std::enable_if<std::is_copy_constructible<T>::value>::type> : std::list<T> {};
// </flame_bait>
}
struct NonCopyable
{
int m_id;
NonCopyable(int id = 0) : m_id(id) {}
NonCopyable(const NonCopyable&) = delete;
NonCopyable& operator = (const NonCopyable&) = delete;
NonCopyable(NonCopyable&&) noexcept = default;
NonCopyable& operator = (NonCopyable&&) noexcept = default;
~NonCopyable() = default;
friend std::ostream& operator<<(std::ostream&, const NonCopyable&);
};
std::ostream& operator<<(std::ostream& os, const NonCopyable& nc) {
os << "I am not a free man, I am number " << nc.m_id;
return os;
}
int main() {
std::vector<xxx::list<NonCopyable>> v;
v.resize(4); // now working
int id = 0;
for (auto& l : v) {
l.emplace_back(++id); // emplace_back one NonCopyable per list
}
xxx::list<NonCopyable> li; // Create a separate list
li.emplace_back(++id); // create one...
v.emplace_back(std::move(li)); // and move list to vector is now working
for (auto& l : v) {
for (auto& nc : l) {
std::cout << nc << "n";
}
}
}
Expected output:
I am not a free man, I am number 1
I am not a free man, I am number 2
I am not a free man, I am number 3
I am not a free man, I am number 4
I am not a free man, I am number 5
Seems I missed the part wherev.resize(4);
fails. What's the error message from that line?
– Ted Lyngmo
Nov 22 at 13:59
1
error C2280: 'NonCopyable::NonCopyable(const NonCopyable &)': attempting to reference a deleted function
. I've added the full error output for that to the post.
– Uri Zarfaty
Nov 22 at 14:11
1
Great! How odd though ... :-) I'll give it a try in VS when I get home.
– Ted Lyngmo
Nov 22 at 14:14
Just to make it worse:v.reserve(4);
gives the same error.
– Ted Lyngmo
Nov 22 at 15:20
1
I added axxx::list
replacement forstd::list
that hopefully should work as a container for both copyable and non-copyable objects. I''m terrible with templates though so be aware ...
– Ted Lyngmo
Nov 22 at 17:47
add a comment |
As @j6t pointed out, it seems it can't be done. A vector with a std::list
with non-copyable elements can not be expanded according to the standard (...). If it was my private project I'd actually consider something like this:
#include <iostream>
#include <vector>
#include <list>
namespace xxx {
// <flame_bait>
template<class T, class Enable = void>
struct list : std::list<T> {
list() : std::list<T>() {}
list(list&&) = default;
list& operator=(list&&) = default;
list(const list&) = delete;
list& operator=(const list&) = delete;
};
template<class T>
struct list<T, typename std::enable_if<std::is_copy_constructible<T>::value>::type> : std::list<T> {};
// </flame_bait>
}
struct NonCopyable
{
int m_id;
NonCopyable(int id = 0) : m_id(id) {}
NonCopyable(const NonCopyable&) = delete;
NonCopyable& operator = (const NonCopyable&) = delete;
NonCopyable(NonCopyable&&) noexcept = default;
NonCopyable& operator = (NonCopyable&&) noexcept = default;
~NonCopyable() = default;
friend std::ostream& operator<<(std::ostream&, const NonCopyable&);
};
std::ostream& operator<<(std::ostream& os, const NonCopyable& nc) {
os << "I am not a free man, I am number " << nc.m_id;
return os;
}
int main() {
std::vector<xxx::list<NonCopyable>> v;
v.resize(4); // now working
int id = 0;
for (auto& l : v) {
l.emplace_back(++id); // emplace_back one NonCopyable per list
}
xxx::list<NonCopyable> li; // Create a separate list
li.emplace_back(++id); // create one...
v.emplace_back(std::move(li)); // and move list to vector is now working
for (auto& l : v) {
for (auto& nc : l) {
std::cout << nc << "n";
}
}
}
Expected output:
I am not a free man, I am number 1
I am not a free man, I am number 2
I am not a free man, I am number 3
I am not a free man, I am number 4
I am not a free man, I am number 5
As @j6t pointed out, it seems it can't be done. A vector with a std::list
with non-copyable elements can not be expanded according to the standard (...). If it was my private project I'd actually consider something like this:
#include <iostream>
#include <vector>
#include <list>
namespace xxx {
// <flame_bait>
template<class T, class Enable = void>
struct list : std::list<T> {
list() : std::list<T>() {}
list(list&&) = default;
list& operator=(list&&) = default;
list(const list&) = delete;
list& operator=(const list&) = delete;
};
template<class T>
struct list<T, typename std::enable_if<std::is_copy_constructible<T>::value>::type> : std::list<T> {};
// </flame_bait>
}
struct NonCopyable
{
int m_id;
NonCopyable(int id = 0) : m_id(id) {}
NonCopyable(const NonCopyable&) = delete;
NonCopyable& operator = (const NonCopyable&) = delete;
NonCopyable(NonCopyable&&) noexcept = default;
NonCopyable& operator = (NonCopyable&&) noexcept = default;
~NonCopyable() = default;
friend std::ostream& operator<<(std::ostream&, const NonCopyable&);
};
std::ostream& operator<<(std::ostream& os, const NonCopyable& nc) {
os << "I am not a free man, I am number " << nc.m_id;
return os;
}
int main() {
std::vector<xxx::list<NonCopyable>> v;
v.resize(4); // now working
int id = 0;
for (auto& l : v) {
l.emplace_back(++id); // emplace_back one NonCopyable per list
}
xxx::list<NonCopyable> li; // Create a separate list
li.emplace_back(++id); // create one...
v.emplace_back(std::move(li)); // and move list to vector is now working
for (auto& l : v) {
for (auto& nc : l) {
std::cout << nc << "n";
}
}
}
Expected output:
I am not a free man, I am number 1
I am not a free man, I am number 2
I am not a free man, I am number 3
I am not a free man, I am number 4
I am not a free man, I am number 5
edited Nov 22 at 17:39
answered Nov 22 at 13:53
Ted Lyngmo
1,927315
1,927315
Seems I missed the part wherev.resize(4);
fails. What's the error message from that line?
– Ted Lyngmo
Nov 22 at 13:59
1
error C2280: 'NonCopyable::NonCopyable(const NonCopyable &)': attempting to reference a deleted function
. I've added the full error output for that to the post.
– Uri Zarfaty
Nov 22 at 14:11
1
Great! How odd though ... :-) I'll give it a try in VS when I get home.
– Ted Lyngmo
Nov 22 at 14:14
Just to make it worse:v.reserve(4);
gives the same error.
– Ted Lyngmo
Nov 22 at 15:20
1
I added axxx::list
replacement forstd::list
that hopefully should work as a container for both copyable and non-copyable objects. I''m terrible with templates though so be aware ...
– Ted Lyngmo
Nov 22 at 17:47
add a comment |
Seems I missed the part wherev.resize(4);
fails. What's the error message from that line?
– Ted Lyngmo
Nov 22 at 13:59
1
error C2280: 'NonCopyable::NonCopyable(const NonCopyable &)': attempting to reference a deleted function
. I've added the full error output for that to the post.
– Uri Zarfaty
Nov 22 at 14:11
1
Great! How odd though ... :-) I'll give it a try in VS when I get home.
– Ted Lyngmo
Nov 22 at 14:14
Just to make it worse:v.reserve(4);
gives the same error.
– Ted Lyngmo
Nov 22 at 15:20
1
I added axxx::list
replacement forstd::list
that hopefully should work as a container for both copyable and non-copyable objects. I''m terrible with templates though so be aware ...
– Ted Lyngmo
Nov 22 at 17:47
Seems I missed the part where
v.resize(4);
fails. What's the error message from that line?– Ted Lyngmo
Nov 22 at 13:59
Seems I missed the part where
v.resize(4);
fails. What's the error message from that line?– Ted Lyngmo
Nov 22 at 13:59
1
1
error C2280: 'NonCopyable::NonCopyable(const NonCopyable &)': attempting to reference a deleted function
. I've added the full error output for that to the post.– Uri Zarfaty
Nov 22 at 14:11
error C2280: 'NonCopyable::NonCopyable(const NonCopyable &)': attempting to reference a deleted function
. I've added the full error output for that to the post.– Uri Zarfaty
Nov 22 at 14:11
1
1
Great! How odd though ... :-) I'll give it a try in VS when I get home.
– Ted Lyngmo
Nov 22 at 14:14
Great! How odd though ... :-) I'll give it a try in VS when I get home.
– Ted Lyngmo
Nov 22 at 14:14
Just to make it worse:
v.reserve(4);
gives the same error.– Ted Lyngmo
Nov 22 at 15:20
Just to make it worse:
v.reserve(4);
gives the same error.– Ted Lyngmo
Nov 22 at 15:20
1
1
I added a
xxx::list
replacement for std::list
that hopefully should work as a container for both copyable and non-copyable objects. I''m terrible with templates though so be aware ...– Ted Lyngmo
Nov 22 at 17:47
I added a
xxx::list
replacement for std::list
that hopefully should work as a container for both copyable and non-copyable objects. I''m terrible with templates though so be aware ...– Ted Lyngmo
Nov 22 at 17:47
add a comment |
Thanks for contributing an answer to Stack Overflow!
- Please be sure to answer the question. Provide details and share your research!
But avoid …
- Asking for help, clarification, or responding to other answers.
- Making statements based on opinion; back them up with references or personal experience.
To learn more, see our tips on writing great answers.
Some of your past answers have not been well-received, and you're in danger of being blocked from answering.
Please pay close attention to the following guidance:
- Please be sure to answer the question. Provide details and share your research!
But avoid …
- Asking for help, clarification, or responding to other answers.
- Making statements based on opinion; back them up with references or personal experience.
To learn more, see our tips on writing great answers.
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53432012%2fnon-copyable-elements-in-a-stdvector-of-stdlists%23new-answer', 'question_page');
}
);
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown