如何为只需要一个参数的类初始化shared_ptr向量?

3
以下是扩展版本,它可以正常运行,但我想使用初始化列表。
vector<shared_ptr<Foo>> inputs = {
    make_shared<Foo>("foo"),
    make_shared<Foo>("bar"),
    make_shared<Foo>("baz")
};

所以我尝试了类似于以下的方法

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

还有两种用法,一种是使用双括号,一种是不使用括号,即{{ "foo" }}"foo"

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

这也无法编译,所以我认为这不是向量的问题,而是使用初始化列表初始化 shared_ptr 的问题。

2个回答

4
唯一合理的版本是你建议的第一个版本。如果您查看std::shared_ptr文档,您会发现没有获得托管对象构造函数参数作为可变模板的构造函数。这意味着您不会找到类似以下内容的东西:
template<class T,class... Arg>
std::shared_ptr<T>::shared_ptr(Args&&... args)

因此,您不能真正像这样做:

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

它不能工作。 对于std::shared_ptr,您可以使用T*构造它,所以这个应该可以工作。
std::shared_ptr<std::string> p(new std::string("hi"));

现在,你可能会想:“嘿!我可以在初始化列表中使用它!”但是不行,这样做是不被允许的:

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

由于特定构造函数上有“explicit”关键字,因此将不起作用,因此必须显式声明!

因此,最终您可以编写类似于:

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

但是正如您自己所看到的,您的第一次尝试要简单得多且更短。

摘要:鉴于没有shared_ptr构造函数将参数传递给托管对象构造函数,因此您无法真正使用{args...}作为有效的语法。鉴于必须明确声明获取T*shared_ptr,因此您无法执行{new T(args..)}之类的操作,因此最简单的方法是使用std::make_shared

P.S. 在您的第一个片段中,用于初始化向量的东西是初始化列表。除了它的类型是std::initializer_list<std::shared_ptr<Foo>>而不是第二个片段中的std::initializer_list<Foo>


1
你可以做一些像这样的傻事:

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

点击这里可以查看实时演示。

只有当T的构造函数接受一个参数时,它才能起作用。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接