聪明的方式来构造类成员std :: vector< std :: unique_ptr< AClass> > [英] Smart way to construct class member std::vector<std::unique_ptr<AClass> >

查看:570
本文介绍了聪明的方式来构造类成员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

解决方案

不要无偿使用矫形器; 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;
};


This question combines unique_ptr as class member and move semantics fail to compile with clang and C++ std::vector in constructor.

My goal is to construct a wrapper

struct V_wrapper{
       std::vector<std::unique_ptr<AClass> > vec;
       V_wrapper(std::vector<std::unique_ptr<AClass> > v) : vec{std::move(v)} {}
};

Unfortunately this code does not compile, because the compiler (clang Apple LLVM version 4.2) attempts to copy construct the vector v which is not supported. On the other hand, if I design an intermediate wrapper for std::unique_ptr<AClass>, as follows

struct P_wrapper{
       std::unique_ptr<AClass> Ptr;
       P_wrapper(std::unique_ptr<AClass>& p) : Ptr(std::move(p)) {}
};

and write V_wrapper as follows

struct V_wrapper{
       std::vector<P_wrapper > vec;
       V_wrapper(std::vector<P_wrapper > v) : vec{std::move(v)} {}
};

then I have no problems. I think (emphasis) that the reason this works is that the constructor of the vector realizes that you should use the reference to move rather than trying to copy, just as in unique_ptr as class member and move semantics fail to compile with clang.

Unfortunately, this leads to the rather inconvenient construction procedure that I make the std::vector<std::unique_ptr<AClass> >, use it to construct the P_wrapper, and finally use that to construct the V_wrapper. I feel that the middle step should be totally redundant! In addition, it makes the interface much harder to read. The whole point of the wrapper in the first place was to hide the implementation of vec from the user, and now there's an inexplicable (not knowing the source code) object P_wrapper that's only used to construct another object....

I want to avoid this, and only have one wrapper. Is there any way of cutting out the middle man so I can go back to the first, much simpler implementation of V_wrapper?

解决方案

Don't use brace initalizers gratuitously; std::vector has a constructor that consumes initializer lists. The obvious way to write this compiles fine for me:

#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;
};

这篇关于聪明的方式来构造类成员std :: vector&lt; std :: unique_ptr&lt; AClass&gt; &gt;的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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