以下代码无法使用Visual Studio 2013进行编译:
#include <vector>
struct X {
X() = default;
X(const X&) = delete;
X& operator=(const X&) = delete;
X(X&&) = delete;
X& operator=(X&&) = delete;
~X() = default;
};
void foo()
{
std::vector<X> v;
std::vector<X> w;
w = std::move(v);
}
错误消息显示
error C2280: 'X::X(X &&)' : attempting to reference a deleted function
这对我没有意义。您不需要X
的移动构造函数来移动vector<X>
。这是编译器错误,还是我错过了什么?
以下是完整的错误消息:
C:\Program Files (x86)\Microsoft Visual Studio 12.0\VC\include\xmemory0(600): error C2280: 'X::X(X &&)' : attempting to reference a deleted function
Test.cpp(9) : see declaration of 'X::X'
C:\Program Files (x86)\Microsoft Visual Studio 12.0\VC\include\xmemory0(723) : see reference to function template instantiation 'void std::allocator<_Ty>::construct<_Objty,_Ty>(_Objty *,_Ty &&)' being compiled
with
[
_Ty=X
, _Objty=X
]
C:\Program Files (x86)\Microsoft Visual Studio 12.0\VC\include\xmemory0(723) : see reference to function template instantiation 'void std::allocator<_Ty>::construct<_Objty,_Ty>(_Objty *,_Ty &&)' being compiled
with
[
_Ty=X
, _Objty=X
]
C:\Program Files (x86)\Microsoft Visual Studio 12.0\VC\include\xmemory0(872) : see reference to function template instantiation 'void std::allocator_traits<_Alloc>::construct<_Ty,_Ty>(std::allocator<_Ty> &,_Objty *,_Ty &&)' being compiled
with
[
_Alloc=std::allocator<X>
, _Ty=X
, _Objty=X
]
C:\Program Files (x86)\Microsoft Visual Studio 12.0\VC\include\xmemory0(872) : see reference to function template instantiation 'void std::allocator_traits<_Alloc>::construct<_Ty,_Ty>(std::allocator<_Ty> &,_Objty *,_Ty &&)' being compiled
with
[
_Alloc=std::allocator<X>
, _Ty=X
, _Objty=X
]
C:\Program Files (x86)\Microsoft Visual Studio 12.0\VC\include\xmemory(378) : see reference to function template instantiation 'void std::_Wrap_alloc<std::allocator<_Ty>>::construct<X,X>(_Ty *,X &&)' being compiled
with
[
_Ty=X
]
C:\Program Files (x86)\Microsoft Visual Studio 12.0\VC\include\xmemory(378) : see reference to function template instantiation 'void std::_Wrap_alloc<std::allocator<_Ty>>::construct<X,X>(_Ty *,X &&)' being compiled
with
[
_Ty=X
]
C:\Program Files (x86)\Microsoft Visual Studio 12.0\VC\include\xmemory(416) : see reference to function template instantiation '_FwdIt std::_Uninit_copy<_InIt,_FwdIt,std::allocator<_Ty>>(_InIt,_InIt,_FwdIt,std::_Wrap_alloc<std::allocator<_Ty>> &,std::_Nonscalar_ptr_iterator_tag)' being compiled
with
[
_FwdIt=X *
, _InIt=std::move_iterator<std::_Vector_iterator<std::_Vector_val<std::_Simple_types<X>>>>
, _Ty=X
]
C:\Program Files (x86)\Microsoft Visual Studio 12.0\VC\include\xmemory(427) : see reference to function template instantiation '_FwdIt std::_Uninit_copy<_Iter,X,_Alloc>(_InIt,_InIt,_FwdIt,_Alloc &)' being compiled
with
[
_FwdIt=X *
, _Iter=std::move_iterator<std::_Vector_iterator<std::_Vector_val<std::_Simple_types<X>>>>
, _Alloc=std::_Wrap_alloc<std::allocator<X>>
, _InIt=std::move_iterator<std::_Vector_iterator<std::_Vector_val<std::_Simple_types<X>>>>
]
C:\Program Files (x86)\Microsoft Visual Studio 12.0\VC\include\vector(1640) : see reference to function template instantiation '_FwdIt std::_Uninitialized_copy<_Iter,X*,std::_Wrap_alloc<std::allocator<_Ty>>>(_InIt,_InIt,_FwdIt,_Alloc &)' being compiled
with
[
_FwdIt=X *
, _Iter=std::move_iterator<std::_Vector_iterator<std::_Vector_val<std::_Simple_types<X>>>>
, _Ty=X
, _InIt=std::move_iterator<std::_Vector_iterator<std::_Vector_val<std::_Simple_types<X>>>>
, _Alloc=std::_Wrap_alloc<std::allocator<X>>
]
C:\Program Files (x86)\Microsoft Visual Studio 12.0\VC\include\vector(789) : see reference to function template instantiation 'X *std::vector<X,std::allocator<_Ty>>::_Ucopy<_Iter>(_Iter,_Iter,X *)' being compiled
with
[
_Ty=X
, _Iter=std::move_iterator<std::_Vector_iterator<std::_Vector_val<std::_Simple_types<X>>>>
]
C:\Program Files (x86)\Microsoft Visual Studio 12.0\VC\include\vector(789) : see reference to function template instantiation 'X *std::vector<X,std::allocator<_Ty>>::_Ucopy<_Iter>(_Iter,_Iter,X *)' being compiled
with
[
_Ty=X
, _Iter=std::move_iterator<std::_Vector_iterator<std::_Vector_val<std::_Simple_types<X>>>>
]
C:\Program Files (x86)\Microsoft Visual Studio 12.0\VC\include\vector(766) : see reference to function template instantiation 'void std::vector<X,std::allocator<_Ty>>::_Construct<_Iter>(_Iter,_Iter,std::forward_iterator_tag)' being compiled
with
[
_Ty=X
, _Iter=std::move_iterator<std::_Vector_iterator<std::_Vector_val<std::_Simple_types<X>>>>
]
C:\Program Files (x86)\Microsoft Visual Studio 12.0\VC\include\vector(766) : see reference to function template instantiation 'void std::vector<X,std::allocator<_Ty>>::_Construct<_Iter>(_Iter,_Iter,std::forward_iterator_tag)' being compiled
with
[
_Ty=X
, _Iter=std::move_iterator<std::_Vector_iterator<std::_Vector_val<std::_Simple_types<X>>>>
]
C:\Program Files (x86)\Microsoft Visual Studio 12.0\VC\include\vector(854) : see reference to function template instantiation 'void std::vector<X,std::allocator<_Ty>>::_Construct<std::move_iterator<std::_Vector_iterator<std::_Vector_val<std::_Simple_types<X>>>>>(_Iter,_Iter)' being compiled
with
[
_Ty=X
, _Iter=std::move_iterator<std::_Vector_iterator<std::_Vector_val<std::_Simple_types<X>>>>
]
C:\Program Files (x86)\Microsoft Visual Studio 12.0\VC\include\vector(854) : see reference to function template instantiation 'void std::vector<X,std::allocator<_Ty>>::_Construct<std::move_iterator<std::_Vector_iterator<std::_Vector_val<std::_Simple_types<X>>>>>(_Iter,_Iter)' being compiled
with
[
_Ty=X
, _Iter=std::move_iterator<std::_Vector_iterator<std::_Vector_val<std::_Simple_types<X>>>>
]
C:\Program Files (x86)\Microsoft Visual Studio 12.0\VC\include\vector(849) : while compiling class template member function 'void std::vector<X,std::allocator<_Ty>>::_Assign_rv(std::vector<_Ty,std::allocator<_Ty>> &&,std::false_type)'
with
[
_Ty=X
]
C:\Program Files (x86)\Microsoft Visual Studio 12.0\VC\include\vector(860) : see reference to function template instantiation 'void std::vector<X,std::allocator<_Ty>>::_Assign_rv(std::vector<_Ty,std::allocator<_Ty>> &&,std::false_type)' being compiled
with
[
_Ty=X
]
Test.cpp(16) : see reference to class template instantiation 'std::vector<X,std::allocator<_Ty>>' being compiled
with
[
_Ty=X
]
答案 0 :(得分:12)
正如评论中的dyp所述,这是一个reported bug in C++11 *。表达式
a = rv
(其中a
是X
类型的容器,其元素类型为T
,而rv
是X
类型的非常量右值)子>
在表99“具有分配器意识的容器要求”中具有以下要求:
如果
allocator_traits<allocator_type>::propagate_on_container_move_assignment ::value
是false
,T
是 MoveInsertable 到X
和 MoveAssignable 。所有a
的现有元素要么被移动分配,要么被销毁。
allocator_traits
具有propagate_on_container_move_assignment
的以下定义:
typedef
见下文propagate_on_container_move_assignment;
如果存在此类型,请输入
Alloc::propagate_on_container_move_assignment
,否则false_type
。
问题在于忘记将相应的typedef放入std::allocator
,因此propagate_on_container_move_assignment
始终为false
。只需添加typedef即可解决C ++ 14的问题。
* 请注意,[default.allocator]和[allocator.traits.types]实际上是N3337中的§20.6,而不是§20.7。
答案 1 :(得分:4)
回答C ++ 11:
VS符合原始规范,因为根据this缺陷报告,std::allocator
导致具有默认分配器的容器的移动赋值运算符不需要的值(
MoveInsertable
和MoveAssignable
值。)
然而,这在C ++ 14中得到了修复。所以现在std::allocator
不再使这个代码成为非法的,根据N3797中的表96,([20.2.1,container.requirements.general]),T
的模板参数std::vector<T> =: X
的要求1}}是
要求:T可从X
中删除
为a = rv
为a
,X
为rv
类型,而{cpnst为X
类型为T
a应等于 rv的值 在此之前 分配,
所以T
没有进一步的要求。我没有在[23.3.6,vector]中找到{{1}}的任何其他要求,所以这应该是C ++ 14中的合法代码(如缺陷报告所示)。