简体   繁体   English

如何为带有一个参数的类初始化一个shared_ptr向量?

[英]How to initialize a vector of shared_ptr for classes that take one parameter?

The following is the expanded version, which works fine, only I'd like to use an initializer list 以下是扩展版本,工作正常,只有我想使用初始化列表

vector<shared_ptr<Foo>> inputs = {
    make_shared<Foo>("foo"),
    make_shared<Foo>("bar"),
    make_shared<Foo>("baz")
};

So I've tried something like 所以我尝试了类似的东西

vector<shared_ptr<Foo>> inputs2 = {
    { "foo" },
    { "bar" },
    { "baz" }
};

as well as with two brackets, or none, ie {{ "foo" }} and just "foo" . 以及两个括号(或不带括号),即{{ "foo" }}和只是"foo"

std::shared_ptr<Foo> foo = { "foo" };

doesn't compile either, so I think this isn't a matter of vectors at all, but initializing shared_ptrs with initializer lists. 也不编译,因此我认为这根本不是向量的问题,而是使用初始化列表初始化初始化shared_ptrs。

The only reasonable version is the first one you suggested. 唯一合理的版本是您建议的第一个版本。
If you look at the std::shared_ptr documentation , you will see that there is no constructor that gets the managed - object constructor arguments as variadic template. 如果查看std :: shared_ptr文档 ,您将看到没有构造函数将可变对象模板的托管对象构造函数参数获取。 Meaning you will not find something like: 意味着您将找不到以下内容:

template<class T,class... Arg>
std::shared_ptr<T>::shared_ptr(Args&&... args)

so you can't really do something like 所以你真的不能做这样的事情

std::shared_ptr<std::string> p("hi there");

It will not work. 不起作用。 What you can do for std::shared_ptr is construct it with T* , so this should work: 您可以使用T*构造std::shared_ptr ,因此应该可以使用:

std::shared_ptr<std::string> p(new std::string("hi"));

Now, you might be thinking, "Hey! I can use it inside an initializer-list!" 现在,您可能会想:“嘿!我可以在初始化列表中使用它!” but no, this: 但不,这:

std::initializer_list<std::shared_ptr<std::string>> il{
        new std::string("hi there"),
        new std::string("hi there")
};

will not work, because that specific constructor has the explicit keyword on it, so it must be declared explicitly! 将不起作用,因为该特定构造函数具有explicit关键字,因此必须显式声明!

So eventually, you can write something like 所以最终,您可以编写类似

std::initializer_list<std::shared_ptr<std::string>> il{
     std::shared_ptr<std::string>(new std::string("hi there"))
};

but as you see yourself, your first attempt is far simpler and shorter. 但是如您所见,您的第一次尝试就简单多了。

Summary: Given the fact that there is no shared_ptr constructor that passes the arguments into the managed object constructor, you can't really use {args...} as a valid syntax. 简介:鉴于没有一个将参数传递到托管对象构造函数的shared_ptr构造函数,您不能真正使用{args...}作为有效语法。 Given the fact that the shared_ptr which gets T* must be declared explicitly, you can't do something like {new T(args..)} , so the simplest way is to use std::make_shared . 鉴于必须明确声明获取T*shared_ptr的事实,因此您无法执行类似{new T(args..)} ,因此最简单的方法是使用std::make_shared

PS In your first snippet, the thing that is used to initialize the vector is initializer list. PS在您的第一个代码段中,用于初始化向量的初始化程序列表。 Except that its type is std::initializer_list<std::shared_ptr<Foo>> and not std::initializer_list<Foo> like the second snippet. 除了它的类型是std::initializer_list<std::shared_ptr<Foo>>而不是std::initializer_list<Foo>像第二个片段一样。

You could do something silly like this: 您可以这样做一些愚蠢的事情:

template< typename Cont >
void consume_append_shared( Cont& c ) {} // terminator

template< typename Cont, typename T, typename... Args >
void consume_append_shared( Cont& c, T&& t, Args&& ...args )
{
    typedef typename Cont::value_type::element_type ElemType;
    c.push_back(
        std::make_shared<ElemType> ( std::forward<T>(t) )
    );
    consume_append_shared( c, std::forward<Args>(args)... );
}

template<typename T, typename... Args>
std::vector< std::shared_ptr<T> > make_shared_vector( Args&& ...args )
{
    std::vector< std::shared_ptr<T> > vec;
    vec.reserve( sizeof...(Args) );
    consume_append_shared( vec, std::forward<Args>(args)... );
    return vec;
}

See it live here 在这里看到它

It only works if T's constructor expect one parameter. 它仅在T的构造函数需要一个参数的情况下起作用。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM