С++ make_shared недоступен

Хотя в моем компиляторе есть std::tr1::shared_ptr<T>, у меня нет make_shared.

Может ли кто-нибудь указать мне на правильную реализацию make_shared? Я вижу, что мне нужно использовать varargs для предоставления аргументов конструктору T.

Но в моем компиляторе также нет вариативных шаблонов.


person user231536    schedule 03.02.2012    source источник
comment
Без вариативных шаблонов вам понадобится несколько версий make_shared, одна для нулевых аргументов, одна для одного аргумента, одна для двух аргументов и т. д.   -  person Ben Voigt    schedule 04.02.2012
comment
Какой компилятор вы используете?   -  person jalf    schedule 04.02.2012
comment
@BenVoigt: Тем не менее, вариативные шаблоны не являются серьезным камнем преткновения. Отсутствие ссылок на rvalue делает make_shared менее мощным в C++03, но вы все равно можете иметь оптимизацию реализации с одним выделением памяти, а также безопасность исключений, которую обеспечивает фабричная функция.   -  person Kerrek SB    schedule 04.02.2012
comment
@Ben: хуже: вам нужно два для одного аргумента, четыре для двух аргументов, восемь для трех аргументов и т. д.   -  person R. Martinho Fernandes    schedule 04.02.2012
comment
@R.MartinhoFernandes: Просветите меня, что различается между двумя версиями каждого аргумента?   -  person Ben Voigt    schedule 04.02.2012
comment
вы можете скопировать существующие реализации (из Boost или компиляторов, поддерживающих последний стандарт, но не использующих вариативные шаблоны) и использовать их. У меня валяется один, но это только msvc, так как он зависит от их std::tr1::_Ref_count_base и _Enable_shared   -  person stijn    schedule 04.02.2012
comment
@Бен: это T const& против T&.   -  person R. Martinho Fernandes    schedule 04.02.2012
comment
@R.MartinhoFernandes: О, T можно явно указать как const something, но не получится ли сделать такой вывод? Да, это выглядит так: ideone.com/c3VF8   -  person Ben Voigt    schedule 04.02.2012
comment
@Бен: точно. T& не выведет foo const&, только foo&. Вот почему Керрек упоминает ссылки на rvalue: T&& может вывести как foo&, так и foo&&.   -  person R. Martinho Fernandes    schedule 04.02.2012


Ответы (1)


Если ваш компилятор не дает реализации make_shared и вы не можете использовать boost, и вас не смущает отсутствие оптимизации однократного размещения как для объекта, так и для счетчика ссылок, то make_shared выглядит примерно так:

Без поддержки вариативных шаблонов:

// zero arguments version
template <typename T>
inline shared_ptr<T> make_shared()
{
  return shared_ptr<T>(new T());
}

// one argument version
template <typename T, typename Arg1>
inline shared_ptr<T> make_shared(Arg1&& arg1)
{
  return shared_ptr<T>(new T(std::forward<Arg1>(arg1)));
}

// two arguments version
template <typename T, typename Arg1, typename Arg2>
inline shared_ptr<T> make_shared(Arg1&& arg1, Arg2&& arg2)
{
  return shared_ptr<T>(new T(std::forward<Arg1>(arg1),
                             std::forward<Arg2>(arg2)));
}

// ...

Если ваш компилятор не поддерживает ссылки на r-значение, создайте 2 версии для каждого аргумента: один const Arg& и один Arg&

С поддержкой вариативных шаблонов:

template <typename T, typename... Args>
inline shared_ptr<T> make_shared(Args&&... args)
{
  return shared_ptr<T>(new T( std::forward<Args>(args)... ));
}
person Gigi    schedule 03.02.2012
comment
Версия Gigi с переменным числом переменных также оставляет правильный след, как обсуждается здесь: .com/questions/9233358/ - person srking; 10.02.2012