Если у меня есть шаблон, который оборачивает стандартный контейнер, кажется, я могу достаточно легко делегировать конструктор initializer_list:
template<typename T>
struct holder {
T t_;
holder() :
t_() {}
holder(std::initializer_list<typename T::value_type> values)
: t_(values) {}
};
Так что это прекрасно работает с std :: vector, например.
int main(int argc, char* argv[]) {
holder<std::vector<int>> y{1,2,3};
return EXIT_SUCCESS;
}
Но это, очевидно, не работает для T как ‘int’ или любого другого типа, который не имеет вложенной value_type typedef. Итак, я хотел бы использовать какой-нибудь метод enable_if или аналогичный трюк, чтобы не вызывать конструктор initializer_list, если только T не определяет вложенный value_type typedef и не может быть создан из std :: initializer_list.
Я попробовал следующее, но это все еще не работает, потому что компилятор (clang ++ 3.1 в моем случае) все еще отключается по недопустимому T :: value_type, когда T является int:
holder(typename std::enable_if<std::is_constructible<T, std::initializer_list<typename T::value_type>>::value, std::initializer_list<typename T::value_type>>::type values)
: t_(values) {}
Любые мысли о том, как выразить концепцию «передайте этот шаблон в T конструктору списка инициализаторов поверх value_type T, если и только если T имеет typedef value_type и может быть создан из initializer_list из T :: value_type».
SFINAE работает только при замене параметров шаблона (следовательно, S в SFINAE). Следующие работы:
template<typename T>
struct holder {
T t_;
holder() :
t_() {}
template<typename U = T>
holder(typename std::enable_if<std::is_constructible<U, std::initializer_list<typename U::value_type>>::value,
std::initializer_list<typename U::value_type>>::type values)
: t_(values) {}
};
Если вы не используете шаблонную функцию, то весь тип будет создан для типа int
(в вашем примере), что приводит к ошибке компилятора.
Обратите внимание, что вы могли бы сделать подпись функции более приятной, если бы использовали дополнительный параметр шаблона:
template<typename U = T, class = typename std::enable_if<std::is_constructible<U, std::initializer_list<typename U::value_type>>::value, bool>::type>
holder(std::initializer_list<typename U::value_type> values)
: t_(values) {}
Других решений пока нет …