使用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
问题描述
我一直在阅读此答案有关从 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:
-
使用
back_inserter
:
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< std :: unique_ptr>>时出错.变成另一个的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!