以下代码是否应该根据C ++ 11产生编译错误(如果是这样的原因?)或VC11是否存在问题?
#include <vector>
#include <list>
#include <memory>
struct A
{
std::vector<std::unique_ptr<int>> v;
};
int main()
{
std::list<A> l;
l.sort([](const A& a1, const A& a2){ return true; });
}
Visual C ++ 2012产生以下编译错误:
1>c:\program files (x86)\microsoft visual studio 11.0\vc\include\xmemory0(606): error C2248: 'std::unique_ptr<_Ty>::unique_ptr' : cannot access private member declared in class 'std::unique_ptr<_Ty>'
1> with
1> [
1> _Ty=int
1> ]
1> c:\program files (x86)\microsoft visual studio 11.0\vc\include\memory(1447) : see declaration of 'std::unique_ptr<_Ty>::unique_ptr'
1> with
1> [
1> _Ty=int
1> ]
1> c:\program files (x86)\microsoft visual studio 11.0\vc\include\xmemory0(605) : while compiling class template member function 'void std::allocator<_Ty>::construct(_Ty *,const _Ty &)'
1> with
1> [
1> _Ty=std::unique_ptr<int>
1> ]
1> c:\program files (x86)\microsoft visual studio 11.0\vc\include\xmemory0(751) : see reference to function template instantiation 'void std::allocator<_Ty>::construct(_Ty *,const _Ty &)' being compiled
1> with
1> [
1> _Ty=std::unique_ptr<int>
1> ]
1> c:\program files (x86)\microsoft visual studio 11.0\vc\include\type_traits(743) : see reference to class template instantiation 'std::allocator<_Ty>' being compiled
1> with
1> [
1> _Ty=std::unique_ptr<int>
1> ]
1> c:\program files (x86)\microsoft visual studio 11.0\vc\include\vector(655) : see reference to class template instantiation 'std::is_empty<_Ty>' being compiled
1> with
1> [
1> _Ty=std::allocator<std::unique_ptr<int>>
1> ]
1> d:\test2\test2.cpp(213) : see reference to class template instantiation 'std::vector<_Ty>' being compiled
1> with
1> [
1> _Ty=std::unique_ptr<int>
1> ]
答案 0 :(得分:4)
这是“VC的一个问题”,但这只是因为你误用了Visual Studio。
VC ++实现r值引用,但不实现编译器生成的移动构造函数/赋值运算符。这意味着,如果你想要一个类型可移动,你必须自己写一个。
A
不是可移动类型,因此各种std::list
函数将尝试复制它们。当他们尝试复制vector
unique_ptr
时,他们会失败。因此编译错误。
如果你想在VC ++中使用移动感知对象,你必须自己为它们编写移动构造函数/赋值。
答案 1 :(得分:3)
问题实际上在VC11中,如it doesn't implement C++11 feature of automatically generating move operations(已经由Nicol Bolas指出)。
以下代码使用VC10 SP1编译;在此代码示例中,移动构造函数是显式编写的(而不是移动operator=
,使用copy-and-swap idiom。)
#include <algorithm> // for std::swap (for copy-and-swap idiom)
#include <list>
#include <memory>
#include <vector>
struct A
{
std::vector<std::unique_ptr<int>> v;
A(A&& other)
: v( std::move(other.v) )
{
}
A& operator=(A other)
{
swap(*this, other);
return *this;
}
friend void swap(A& lhs, A& rhs)
{
using std::swap;
swap(lhs.v, rhs.v);
}
};
int main()
{
std::list<A> l;
l.sort( []( const A& , const A& ){ return true; } );
}
答案 2 :(得分:0)
这是Visual C ++ 2012的一个问题(Microsoft在Connect上承认:Compile error in C++ code sorting a list of objects holding a vector of unique_ptr)并且它已在Visual C ++ 2013中修复。
另外,我想指出一个问题与事实无关,即Visual C ++不会隐式生成移动构造函数。如果你在结构A中显式删除了所有复制和移动构造函数(是的,它将使得不可能将类型A的对象插入到列表中,但这不是重点)在我的原始示例中,代码仍然不应该复制或移动任何对象和因此产生编译错误:
#include <vector>
#include <list>
#include <memory>
struct A
{
std::vector<std::unique_ptr<int>> v;
A(A&&) = delete;
A(const A&) = delete;
};
int main()
{
std::list<A> l;
l.sort([](const A& a1, const A& a2){ return true; });
}