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

时间:2015-10-05 02:02:13

标签: c++ c++11

以下是扩展版本,工作正常,我只想使用初始化列表

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_ptrs。

2 个答案:

答案 0 :(得分:4)

唯一合理的版本是您建议的第一个版本 如果查看std::shared_ptr documentation,您将看到没有构造函数将托管 - 对象构造函数参数作为可变参数模板获取。意思是你找不到像这样的东西:

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

不起作用, 因为该特定的构造函数在其上具有显式关键字,所以必须明确声明它!

所以最终,你可以写一些像

这样的东西
std::initializer_list<std::shared_ptr<std::string>> il{
     std::shared_ptr<std::string>(new std::string("hi there"))
};

但正如您所见,您的第一次尝试更简单,更短。

summery:鉴于没有将参数传递给manged对象构造函数的shared_ptr构造函数,您无法真正使用{args ...}作为有效语法。鉴于必须明确声明获得T*的shared_ptr,你不能像{new T(args ..)}那样做,所以最简单的方法是使用std::make_shared

PS。在你的第一个片段中,用于初始化向量的东西是初始化列表。只有它的类型是std::initializer_list<std::shared_ptr<Foo>>而不是std::initializer_list<Foo>,就像第二个片段一样。

答案 1 :(得分: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;
}

直播here

只有在T&#39的构造函数需要一个参数时才有效。