Optionally supporting initializer_list construction for templates maybe wrapping containers

c++, c++11, enable-if, initializer-list, templates

Solution

SFINAE only works on template parameter subsitution(hence the S in SFINAE). The following works:

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) {}

};

If you didn't use a template function, then the whole class would be instantiated for the type `int`(in your example), leading to a compiler error.

Note that you could make the function signature nicer if you used an extra template parameter:

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) {}

Problem

If I have a template that wraps a standard container, it seems I can reasonably easily delegate the initializer_list constructor: ``` template<typename T> struct holder { T t_; holder() : t_() {} holder(std::initializer_list<typename T::value_type> values) : t_(values) {} }; ``` So this works nicely with std::vector, for instance. ``` int main(int argc, char* argv[]) { holder<std::vector<int>> y{1,2,3}; return EXIT_SUCCESS; } ``` But it pretty obviously doesn't work for T as 'int', or any other type that doesn't have a nested value_type typedef. So, I'd like to use some sort of enable_if or similar trick to make the initializer_list constructor not be emitted unless T both defines a nested value_type typedef, and is constructible from std::initializer_list. I tried the following, but it still doesn't work, because the compiler (clang++ 3.1 in my case), still trips over the invalid T::value_type when T is 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) {} ``` Any thoughts on how to express the concept "give this template on T an initializer list constructor over T's value_type, if and only if T has a value_type typedef and is constructible from an initializer_list of T::value_type".

Original source