2015-10-05 5 views
1

Ниже приводится расширенная версия, которая работает отлично, только я хотел бы использовать список InitializerКак инициализировать вектор shared_ptr для классов, которые принимают один параметр?

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 со списками инициализатора.

ответ

3

единственная разумная версия - первая, которую вы предложили.
Если вы посмотрите на std::shared_ptr documentation, вы увидите, что нет конструктора, который получает аргументы конструктора управляемых объектов в качестве вариационного шаблона. означает, что вы не найдете Somthing как:

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

так вы не можете действительно сделать Somthing как

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

не будет работать, потому что конкретные costructor имеют явное ключевое слово на нем, поэтому он должен быть явно объявлены!

так в конце концов, вы можете написать что-то вроде

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

но, как вы видите себя, ваша первая попытка гораздо проще и короче.

summery: учитывая тот факт, что конструктор shared_ptr отсутствует, который передает аргументы в конструктор manged object, вы не можете использовать {args ...} как допустимый синтаксис. учитывая, что shared_ptr, который получает T*, должен быть явно указан, вы не можете сделать что-то вроде {new T (args ..)}, поэтому самым простым способом является использование std::make_shared.

пс. в вас первый фрагмент, вещь, которая используется для инициализации вектора : список инициализаторов. только то, что это тип 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; 
} 

Посмотреть вживую here

Он работает только тогда, когда конструктор T ожидают один параметр.

Смежные вопросы