C++ Предоставить конструктор списка инициализаторов для шаблона класса

У меня есть шаблон класса Templ с параметром шаблона T, а класс Templ имеет член данных типа T, называемый obj. Я написал шаблон конструктора переменной, который пересылает аргументы в конструктор obj:

template <class T>
class Templ
{
public:
     template <class... Args> explicit Templ (Args&&... args)
     : obj (std::forward<Args>(args)...)
     {
     }
private:
     T obj;
};

Теперь я понял, что тип T может быть классом с конструктором списка инициализации, и я хочу, чтобы он был доступен через Templ. Итак, я проверил, что std::list::emplace а также std::make_shared делать. Они имеют переменную функцию, как у меня, но у них нет переопределений, принимающих список инициализации. По какой-то причине.

Итак, первый вопрос: почему? Я имею в виду, что если я использую некоторый класс T с ctor списка инициализации, а затем я использую std::list<T>? Почему list::emplace не имеет версии, которая принимает initializer_list? Может быть, есть веская причина, по которой я должен это сделать... так что я хочу знать.

Кроме того, независимо от того, что делает STL - я должен предоставить ctor init-list как хороший дизайн? Я имею в виду, это так же, как вариационный ctor, верно? Позволяет пользователю выбрать любой тип или класс T для использования с Templ<> и напрямую вызывать любой ctor, определенный для T. Даже если это ctor, принимающий список инициализации.

1 ответ

Решение

Проблема с пересылкой initializer_list конструкторы в том, что все типы аргументов, кроме самых тривиальных, не выводимы ( шаблоны не всегда предполагают типы списков инициализаторов):

#include <map>
template<typename T> struct U {
   T t;
   template<typename...A> explicit U(A&&...a): t(std::forward<A>(a)...) {}
   template<typename L, typename = typename std::enable_if<
      std::is_constructible<T, std::initializer_list<L>>::value>::type>
      explicit U(std::initializer_list<L> l): t(l) {}
};
U<std::map<int, int>> m{{{0, 1}, {2, 3}}};  // fails, couldn't deduce 'L'

Так как вам придется написать m{std::initializer_list<...>{...}} в большинстве случаев нет особого смысла предоставлять его только для примитивов, и уж точно не для стандарта.

Если вы думаете что нибудь интересное initializer_list Скорее всего, аргументы относятся к типам контейнеров, вы можете посмотреть на подход, принятый в разделе " Опционально", поддерживающем конструкцию initializer_list для шаблонов, возможно, упаковывающих контейнеры.

Другие вопросы по тегам