使用std :: make_move_iterator插入std :: list< std :: unique_ptr>>时出错.变成另一个 [英] Error when using std::make_move_iterator to insert a std::list<std::unique_ptr>> into another one

查看:102
本文介绍了使用std :: make_move_iterator插入std :: list< std :: unique_ptr>>时出错.变成另一个的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我一直在阅读此答案有关从 std :: vector< std ::中移动元素的问题使用 std :: make_move_iterator 将unique_ptr< T>> 转换为另一个.它可以完美地工作:

I've been reading this answer about moving elements from a std::vector<std::unique_ptr<T>> to another one using std::make_move_iterator. It works flawlessly:

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()));

现在,我尝试将其更改为使用其他容器( std :: list ):

Now I tried to change it to use a different container (std::list):

std::list<std::unique_ptr<int>> c1;
std::list<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_ptr< _Ty> :: unique_ptr':无法访问在类'std :: unique_ptr< _Ty>'中声明的私有成员

error C2248: 'std::unique_ptr<_Ty>::unique_ptr' : cannot access private member declared in class 'std::unique_ptr<_Ty>'

但是,如果列表包含其他对象(例如 std :: string ),它确实可以工作:

However, it does work if lists contain other objects (like std::string):

std::list<std::string> s1;
std::list<std::string> s2;
s2.insert(s2.end(), std::make_move_iterator(s1.begin()), std::make_move_iterator(s1.end()));

现在,如果我使用同一问题的另一个答案,则使用 std :: back_inserter std :: move ,它与 std :: vector std :: list :

Now, if I use another answer from the same question, which uses std::back_inserter and std::move, it works with both std::vector and std::list:

std::list<std::unique_ptr<int>> c1;
std::list<std::unique_ptr<int>> c2;
c1.push_back(std::unique_ptr<int>(new int));
std::move(c1.begin(), c1.end(), std::back_inserter(c2));

据我了解,此解决方案基本上是在向后插入第二个容器时逐个移动每个项目.

As far as I understand, this solution basically moves each item individually when back inserting on the second container.

我的问题是,为什么在 std :: unique_ptr std :: list 上使用 std :: make_move_iterator 无效,但是 std :: vector 还是列表元素的类型不同?

My question is, why using std::make_move_iterator on a std::list of std::unique_ptr doesn't work but it does with std::vector or if the list element is of a different type?

注意:我正在使用Visual Studio 2010.

Note: I'm using Visual Studio 2010.

推荐答案

核心问题是Visual Studio 2010的 std :: list :: insert 实现不支持移动语义.在内部, std :: list :: insert 调用称为 _Insert 的方法,该方法在VS 2010中声明如下:

The core problem is that Visual Studio 2010's implementation of std::list::insert doesn't support moving semantics. Internally, the std::list::insert invokes a method called _Insert, which is declared as follows in VS 2010:

void _Insert(const_iterator _Where, const _Ty& _Val)

在VS 2017中(未检查其他版本),它调用相同的方法,但声明为:

In VS 2017 (not checked for other versions), it calls the same method but it is declared as:

void _Insert(_Unchecked_const_iterator _Where, _Valty&&... _Val)

如所见,VS 2017使用右值引用,因此在插入时调用 std :: unique_ptr 的移动构造函数.另一方面,VS 2010改用左值引用,因此有时会调用复制构造函数,该构造函数被声明为 std :: unique_ptr 私有,从而产生编译错误.

As seen, VS 2017 uses an rvalue reference, therefore calling the moving constructor of std::unique_ptr when making the insertion. On the other hand, VS 2010 uses an lvalue reference instead, so at some moment the copy constructor is called, which is declared private for std::unique_ptr, generating the compilation error.

结论

在VS 2010中,无法使用基于 std :: make_move_iterator 的解决方案,因为如何实现 std :: list :: insert .将 std :: list< std :: unique_ptr< T>>> 附加到另一个选项的选项包括:

In VS 2010 there is no way to use the solution based on std::make_move_iterator because how std::list::insert is implemented. Options for appending a std::list<std::unique_ptr<T>> into another one include:

std::move(c1.begin(), c1.end(), std::back_inserter(c2));

  • 使用 std :: list :: splice (记入

  • Using std::list::splice (credit to @T.C.), which is very useful since it can be directly used with lists returned by functions:

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

  • 这篇关于使用std :: make_move_iterator插入std :: list&lt; std :: unique_ptr&gt;&gt;时出错.变成另一个的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

    查看全文
    相关文章
    登录 关闭
    扫码关注1秒登录
    发送“验证码”获取 | 15天全站免登陆