我看到std::vector< std::unique_ptr< T > >
与std::move
一起传递了一些错误。重现问题的代码是:
#include <memory> // for std::unique_ptr
#include <utility> // for std::move
#include <vector> // for std::vector
struct bar {};
using vtype = std::vector<std::unique_ptr<bar>>;
struct foo
{
foo(vtype v) : _v(std::move(v)) { }
private:
vtype _v;
};
vtype getVector()
{
return { std::move( std::unique_ptr<bar>(new bar()) ) };
};
int main()
{
foo f(std::move(getVector()));
};
使用clang 3.4,此代码会产生此错误:
$ clang++ -std=c++11 test.cpp -o xtest
In file included from test.cpp:1:
In file included from /usr/bin/../lib/gcc/x86_64-linux-gnu/4.8/../../../../include/c++/4.8/memory:64:
/usr/bin/../lib/gcc/x86_64-linux-gnu/4.8/../../../../include/c++/4.8/bits/stl_construct.h:75:38: error: call to deleted constructor of
'std::unique_ptr<bar, std::default_delete<bar> >'
{ ::new(static_cast<void*>(__p)) _T1(std::forward<_Args>(__args)...); }
^ ~~~~~~~~~~~~~~~~~~~~~~~~~~~
/usr/bin/../lib/gcc/x86_64-linux-gnu/4.8/../../../../include/c++/4.8/bits/stl_uninitialized.h:75:8: note: in instantiation of function template specialization
'std::_Construct<std::unique_ptr<bar, std::default_delete<bar> >, const std::unique_ptr<bar, std::default_delete<bar> > &>' requested here
std::_Construct(std::__addressof(*__cur), *__first);
^
/usr/bin/../lib/gcc/x86_64-linux-gnu/4.8/../../../../include/c++/4.8/bits/stl_uninitialized.h:117:2: note: in instantiation of function template specialization
'std::__uninitialized_copy<false>::__uninit_copy<const std::unique_ptr<bar, std::default_delete<bar> > *, std::unique_ptr<bar, std::default_delete<bar> > *>'
requested here
__uninit_copy(__first, __last, __result);
^
/usr/bin/../lib/gcc/x86_64-linux-gnu/4.8/../../../../include/c++/4.8/bits/stl_uninitialized.h:258:19: note: in instantiation of function template specialization
'std::uninitialized_copy<const std::unique_ptr<bar, std::default_delete<bar> > *, std::unique_ptr<bar, std::default_delete<bar> > *>' requested here
{ return std::uninitialized_copy(__first, __last, __result); }
^
/usr/bin/../lib/gcc/x86_64-linux-gnu/4.8/../../../../include/c++/4.8/bits/stl_vector.h:1204:11: note: in instantiation of function template specialization
'std::__uninitialized_copy_a<const std::unique_ptr<bar, std::default_delete<bar> > *, std::unique_ptr<bar, std::default_delete<bar> > *, std::unique_ptr<bar,
std::default_delete<bar> > >' requested here
std::__uninitialized_copy_a(__first, __last,
^
/usr/bin/../lib/gcc/x86_64-linux-gnu/4.8/../../../../include/c++/4.8/bits/stl_vector.h:368:2: note: in instantiation of function template specialization
'std::vector<std::unique_ptr<bar, std::default_delete<bar> >, std::allocator<std::unique_ptr<bar, std::default_delete<bar> > > >::_M_range_initialize<const
std::unique_ptr<bar, std::default_delete<bar> > *>' requested here
_M_range_initialize(__l.begin(), __l.end(),
^
test.cpp:17:12: note: in instantiation of member function 'std::vector<std::unique_ptr<bar, std::default_delete<bar> >, std::allocator<std::unique_ptr<bar,
std::default_delete<bar> > > >::vector' requested here
return { std::move( std::unique_ptr<bar>(new bar()) ) };
^
/usr/bin/../lib/gcc/x86_64-linux-gnu/4.8/../../../../include/c++/4.8/bits/unique_ptr.h:273:7: note: function has been explicitly marked deleted here
unique_ptr(const unique_ptr&) = delete;
^
1 error generated.
使用g ++ 4.8,情况似乎没有任何好处:
$ g++-4.8 -std=c++11 test.cpp -o xtest
In file included from /usr/include/c++/4.8/memory:64:0,
from test.cpp:1:
/usr/include/c++/4.8/bits/stl_construct.h: In instantiation of ‘void std::_Construct(_T1*, _Args&& ...) [with _T1 = std::unique_ptr<bar>; _Args = {const std::unique_ptr<bar, std::default_delete<bar> >&}]’:
/usr/include/c++/4.8/bits/stl_uninitialized.h:75:53: required from ‘static _ForwardIterator std::__uninitialized_copy<_TrivialValueTypes>::__uninit_copy(_InputIterator, _InputIterator, _ForwardIterator) [with _InputIterator = const std::unique_ptr<bar>*; _ForwardIterator = std::unique_ptr<bar>*; bool _TrivialValueTypes = false]’
/usr/include/c++/4.8/bits/stl_uninitialized.h:117:41: required from ‘_ForwardIterator std::uninitialized_copy(_InputIterator, _InputIterator, _ForwardIterator) [with _InputIterator = const std::unique_ptr<bar>*; _ForwardIterator = std::unique_ptr<bar>*]’
/usr/include/c++/4.8/bits/stl_uninitialized.h:258:63: required from ‘_ForwardIterator std::__uninitialized_copy_a(_InputIterator, _InputIterator, _ForwardIterator, std::allocator<_Tp>&) [with _InputIterator = const std::unique_ptr<bar>*; _ForwardIterator = std::unique_ptr<bar>*; _Tp = std::unique_ptr<bar>]’
/usr/include/c++/4.8/bits/stl_vector.h:1206:27: required from ‘void std::vector<_Tp, _Alloc>::_M_range_initialize(_ForwardIterator, _ForwardIterator, std::forward_iterator_tag) [with _ForwardIterator = const std::unique_ptr<bar>*; _Tp = std::unique_ptr<bar>; _Alloc = std::allocator<std::unique_ptr<bar> >]’
/usr/include/c++/4.8/bits/stl_vector.h:369:36: required from ‘std::vector<_Tp, _Alloc>::vector(std::initializer_list<_Tp>, const allocator_type&) [with _Tp = std::unique_ptr<bar>; _Alloc = std::allocator<std::unique_ptr<bar> >; std::vector<_Tp, _Alloc>::allocator_type = std::allocator<std::unique_ptr<bar> >]’
test.cpp:17:59: required from here
/usr/include/c++/4.8/bits/stl_construct.h:75:7: error: use of deleted function ‘std::unique_ptr<_Tp, _Dp>::unique_ptr(const std::unique_ptr<_Tp, _Dp>&) [with _Tp = bar; _Dp = std::default_delete<bar>]’
{ ::new(static_cast<void*>(__p)) _T1(std::forward<_Args>(__args)...); }
^
In file included from /usr/include/c++/4.8/memory:81:0,
from test.cpp:1:
/usr/include/c++/4.8/bits/unique_ptr.h:273:7: error: declared here
unique_ptr(const unique_ptr&) = delete;
^
根据this answer和评论,这不应该在这些编译器上发生,但我不是完全一样:我正在尝试使用初始化列表初始化向量。
知道为了正确构建此代码需要做些什么?
答案 0 :(得分:9)
在getVector
return { std::move( std::unique_ptr<bar>(new bar()) ) };
导致调用带有std::vector<T>
参数的initializer_list<T>
构造函数。即使您正在移动unique_ptr
,initializer_list
only allows const
access to its elements,vector
会尝试复制unique_ptr
,导致你看错了。
您可以通过采用更详细的方式构建vector
vtype getVector()
{
vtype v;
v.push_back(std::unique_ptr<bar>(new bar()));
return v;
}
出于好奇心的考虑,可以从一系列仅移动对象中构造vector
,但是您需要通过std::move_iterator
来移动元素。
vtype getVector()
{
std::unique_ptr<bar> arr[] = {std::unique_ptr<bar>(new bar())};
return {std::make_move_iterator(std::begin(arr)),
std::make_move_iterator(std::end(arr))};
}
答案 1 :(得分:-1)
你的vtype是一个唯一指针的向量,你会返回一个唯一的指针。
因为你在构造函数foo中进行移动,所以你不需要返回一个移动 看看这段代码:
#include <memory> // for std::unique_ptr
#include <utility> // for std::move
#include <vector> // for std::vector
struct bar {};
using vtype = /*std::vector<*/std::unique_ptr<bar>/*>*/;
struct foo
{
foo(vtype v) : _v(std::move(v)) { }
private:
vtype _v;
};
vtype getVector()
{
return /*{ std::move(*/ std::unique_ptr<bar>(new bar()) /*) }*/;
};
int main()
{
foo f(std::move(getVector()));
};