[英]make template class with std::vector<T> non-copyable when T is non-copyable
[英]Non-copyable elements in a std::vector of std::lists
我有一個不可復制的類,簡化如下:
struct NonCopyable
{
NonCopyable() = default;
NonCopyable(const NonCopyable&) = delete;
NonCopyable& operator = (const NonCopyable&) = delete;
NonCopyable(NonCopyable&&) = default;
NonCopyable& operator = (NonCopyable&&) = default;
};
我將此類的對象存儲在各種std :: lists中。 某一時刻,我有一個空的 std :: vector這些列表,我想調整其大小以包含固定數量的空列表。 但是,這抱怨缺少NonCopyable復制構造函數,盡管(據我所知)它不應該嘗試構造任何NonCopyable!
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
為什么是這樣? 沒有使類可復制的方法,有什么辦法嗎?
我將VS2017與/ std:c ++ 17一起使用,以防萬一。
這是嘗試調整大小的完整錯誤輸出(上面的前兩行)。
1>------ Build started: Project: testcore, Configuration: Debug x64 ------
1>testcard.cpp
1>c:\program files (x86)\microsoft visual studio\2017\community\vc\tools\msvc\14.15.26726\include\xmemory0(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 studio\2017\community\vc\tools\msvc\14.15.26726\include\list(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 studio\2017\community\vc\tools\msvc\14.15.26726\include\list(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 studio\2017\community\vc\tools\msvc\14.15.26726\include\list(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 studio\2017\community\vc\tools\msvc\14.15.26726\include\list(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 studio\2017\community\vc\tools\msvc\14.15.26726\include\list(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 studio\2017\community\vc\tools\msvc\14.15.26726\include\list(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 studio\2017\community\vc\tools\msvc\14.15.26726\include\list(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 studio\2017\community\vc\tools\msvc\14.15.26726\include\list(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 studio\2017\community\vc\tools\msvc\14.15.26726\include\list(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 studio\2017\community\vc\tools\msvc\14.15.26726\include\list(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 studio\2017\community\vc\tools\msvc\14.15.26726\include\list(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 studio\2017\community\vc\tools\msvc\14.15.26726\include\xmemory0(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 studio\2017\community\vc\tools\msvc\14.15.26726\include\vector(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 studio\2017\community\vc\tools\msvc\14.15.26726\include\vector(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 studio\2017\community\vc\tools\msvc\14.15.26726\include\vector(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 ==========
std::list
不是noexcept-movable ,但是是可復制的。 因此,無論如何, std::vector
希望list
的copy-constructor優於其move-constructor。
要變通解決此問題,您必須將std::list
包裝在不可復制的類中。
正如@ j6t指出的那樣,似乎無法完成。 帶有std::list
且具有不可復制元素的向量不能根據標准(...)進行擴展。 如果這是我的私人項目,我實際上會考慮這樣的事情:
#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";
}
}
}
預期產量:
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
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.