C++11 使用std::make\u move\u迭代器插入std::list时出错<;标准::唯一性\u ptr>&燃气轮机;换成另一个

C++11 使用std::make\u move\u迭代器插入std::list时出错<;标准::唯一性\u ptr>&燃气轮机;换成另一个,c++11,linked-list,insert,move-semantics,unique-ptr,C++11,Linked List,Insert,Move Semantics,Unique Ptr,我一直在阅读有关使用std::make\u move\u迭代器将元素从std::vector移动到另一个元素的内容。它可以完美地工作: std::vector<std::unique_ptr<int>> c1; std::vector<std::unique_ptr<int>> c2; c1.push_back(std::unique_ptr<int>(new int)); c2.insert(c2.end(), std::make_m

我一直在阅读有关使用
std::make\u move\u迭代器将元素从
std::vector
移动到另一个元素的内容。它可以完美地工作:

std::vector<std::unique_ptr<int>> c1;
std::vector<std::unique_ptr<int>> c2;
c1.push_back(std::unique_ptr<int>(new int));
c2.insert(c2.end(), std::make_move_iterator(c1.begin()), std::make_move_iterator(c1.end()));
但编译失败的原因是:

错误C2248:“std::unique\u ptr::unique\u ptr”:无法访问在类“std::unique\u ptr”中声明的私有成员

但是,如果列表包含其他对象(如
std::string
),则它确实有效:

据我所知,此解决方案基本上在向后插入第二个容器时分别移动每个项目

我的问题是,为什么在
std::unique\u ptr
std::list
上使用
std::make\u move\u迭代器不起作用,但它与
std::vector
一起使用,或者如果列表元素是不同类型的


注意:我使用的是Visual Studio 2010。

核心问题是Visual Studio 2010对
std::list::insert
的实现不支持移动语义。在内部,
std::list::insert
调用一个名为
\u insert
的方法,该方法在VS 2010中声明如下:

void _Insert(const_iterator _Where, const _Ty& _Val)
在VS 2017中(未检查其他版本),它调用相同的方法,但声明为:

void _Insert(_Unchecked_const_iterator _Where, _Valty&&... _Val)
如图所示,VS 2017使用右值引用,因此在进行插入时调用
std::unique_ptr
的移动构造函数。另一方面,VS 2010使用左值引用,因此在某个时刻调用复制构造函数,该构造函数被声明为私有的
std::unique_ptr
,生成编译错误


结论

在VS 2010中,无法使用基于
std::make\u move\u iterator
的解决方案,因为
std::list::insert
是如何实现的。将
std::list
附加到另一个列表中的选项包括:

  • 使用:

  • 使用(credit to),这非常有用,因为它可以直接用于函数返回的列表:

    c2.splice(c2.end(), c1);
    

VS2010很古老。与VS2017。有趣的。。。谢谢我想知道它是否有解决办法?如问题中所述,我有另一个解决方案,但我暂时无法从VS 2010迁移。对于在列表之间移动,您可能应该使用
splice
。很好的建议,谢谢!正如你所说,它实际上是更直接和自我记录的
void _Insert(const_iterator _Where, const _Ty& _Val)
void _Insert(_Unchecked_const_iterator _Where, _Valty&&... _Val)
std::move(c1.begin(), c1.end(), std::back_inserter(c2));
c2.splice(c2.end(), c1);