Enforce variadic template of certain type

后端 未结 4 1657
执念已碎
执念已碎 2020-12-31 02:35

I would like to enforce the type of variadic template to be identical to an earlier set template type. In the below example, I\'d like T and U to be the same type.

c

相关标签:
4条回答
  • std::conjunction (logical AND) was introduced in C++17 so one doesn't have to implement all_same manually anymore. Then the constructor becomes simply:

    template<typename... U,
        typename = std::enable_if_t<
            std::conjunction_v<
                std::is_same<T, U>...
            >
        >
    >
    Foo(T first, U... vals)
    {
        std::cout << "Called multiple argument ctor" << std::endl;
        // [...]   
    }
    

    See live example.

    0 讨论(0)
  • 2020-12-31 03:19

    We can use SFINAE to ensure that all U types are the same as T. An important thing to note is that U is not just one type as you imply, but a list of possibly disparate types.

    template<class... U, std::enable_if_t<all_same<T, U...>::value>* = nullptr>
    Foo(T first, U... vals) {
        std::cout << "Called multiple argument ctor" << std::endl;
        // [...]   
    }
    

    std::enable_if_t is from C++14. If that's not an option for you, just use std::enable_if.

    typename std::enable_if<all_same<T, U...>::value>::type* = nullptr>
    

    all_same can be implemented in a bunch of different ways. Here's a method I like using boolean packs:

    namespace detail
    {
        template<bool...> struct bool_pack;
        template<bool... bs>
        //if any are false, they'll be shifted in the second version, so types won't match
        using all_true = std::is_same<bool_pack<bs..., true>, bool_pack<true, bs...>>;
    }
    template <typename... Ts>
    using all_true = detail::all_true<Ts::value...>;
    
    template <typename T, typename... Ts>
    using all_same = all_true<std::is_same<T,Ts>...>;
    
    0 讨论(0)
  • 2020-12-31 03:25

    Without implementing of all_same you could also change the constructor code as follows:

    template<class F, typename = typename enable_if<is_same<F, T>::value>::type, class... U>
        Foo(F first, U... vals): Foo(vals...) {
        std::cout << "Called multiple argument ctor" << std::endl;
        // [...]   
    }
    

    is_same is the function in an STL <type_traits>

    0 讨论(0)
  • 2020-12-31 03:27

    If all parameters are required to be the same type AND the number of parameters is variable,

    Variadic templates are too heavy for those requirements, just use C++11 std::initializer_list.

    They just do the job if you can replace () with {} on the call.

    template<class T> struct Foo {
        Foo(T val) {
            std::cout << "Called single argument ctor" << std::endl;
        }
        // Enforce all parameters to be the same type :
        Foo( std::initializer_list<T> values ) {
            std::cout << "Called multiple argument ctor" << std::endl;
            for (T value : values)
                cout << value << endl;
        }
    };
    
    int main() {
        // Work as expected.
        Foo<int> single(1);
        // Work as expected.
        Foo<int> multiple{ 1, 2, 3, 4, 5 };
        // Doesn't work - as required :
        //Foo<int> mixedtype{ 1, "a", "b", "c" };
    
    }
    
    0 讨论(0)
提交回复
热议问题