[英]Smart way to construct class member std::vector<std::unique_ptr<AClass> >
此问题将unique_ptr组合为类成员,并且移动语义无法使用 构造函数中的 clang和C ++ std :: vector 进行编译 。
我的目标是构造一个包装器
struct V_wrapper{
std::vector<std::unique_ptr<AClass> > vec;
V_wrapper(std::vector<std::unique_ptr<AClass> > v) : vec{std::move(v)} {}
};
不幸的是,该代码无法编译,因为编译器(clang Apple LLVM版本4.2)试图复制构造不支持的向量v
。 另一方面,如果我为std::unique_ptr<AClass>
设计一个中间包装器,如下所示
struct P_wrapper{
std::unique_ptr<AClass> Ptr;
P_wrapper(std::unique_ptr<AClass>& p) : Ptr(std::move(p)) {}
};
并如下编写V_wrapper
struct V_wrapper{
std::vector<P_wrapper > vec;
V_wrapper(std::vector<P_wrapper > v) : vec{std::move(v)} {}
};
那我就没问题 我认为(强调)之所以起作用,是因为向量的构造函数意识到您应该使用引用来移动而不是尝试复制,就像在unique_ptr中作为类成员一样,移动语义无法用clang编译 。
不幸的是,这导致了相当不便的构造过程,即我制作了std::vector<std::unique_ptr<AClass> >
,使用它来构造P_wrapper
,最后使用它来构造V_wrapper
。 我觉得中间步骤应该是完全多余的! 此外,它使界面更难以阅读。 包装器的全部目的是要向用户隐藏vec
的实现,现在有一个莫名其妙的(不知道源代码)对象P_wrapper
,该对象仅用于构造另一个对象。
我要避免这种情况,并且只有一个包装器。 有什么办法可以减少中间人的工作,以便我可以回到第一个更简单的V_wrapper
实现?
您需要删除默认的复制构造函数和赋值运算符。 这些函数是隐式定义的,需要显式删除,因为它们将尝试复制向量及其内容(这是对unique_ptr
的非法操作)。
struct V_wrapper
{
public:
V_wrapper(std::vector<std::unique_ptr<AClass> > v)
: vec(std::move(v))
{}
// Delete default copy constructor + assignment operator
V_wrapper(const V_wrapper &) = delete;
V_wrapper& operator= (const V_wrapper &) = delete;
private:
std::vector<std::unique_ptr<AClass> > vec;
};
不要随意使用大括号启动器; std::vector
具有使用初始化程序列表的构造函数。 编写此代码的明显方法对我来说很好:
#include <memory> // for std::unique_ptr
#include <utility> // for std::move
#include <vector> // for std::vector
struct bar {};
struct foo
{
using vtype = std::vector<std::unique_ptr<bar>>;
foo(vtype v) : _v(std::move(v)) { }
private:
vtype _v;
};
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.