Check for arguments type in a variadic template declaration

前端 未结 3 1299
终归单人心
终归单人心 2020-12-19 15:22

I got a plain variadic template declaration, just like the classic one:

template 
class VariadicTemplate;

What

相关标签:
3条回答
  • 2020-12-19 15:37
    struct Foo {};
    
    #include <type_traits>
    
    template<class T, class...>
    struct are_same : std::true_type
    {};
    
    template<class T, class U, class... TT>
    struct are_same<T, U, TT...>
        : std::integral_constant<bool, std::is_same<T,U>{} && are_same<T, TT...>{}>
    {};
    
    template<typename... Arguments>
    class VariadicTemplate
    {
        static_assert(are_same<Foo, Arguments...>{}, "a meaningful error message");
    };
    
    int main()
    {
        VariadicTemplate<Foo, Foo, Foo, Foo> v0{}; (void)v0;
        VariadicTemplate<Foo, int, Foo, double> v1{}; (void)v1;
    }
    

    But something tells me you want to know if the arguments are all specializations of a class template Foo:

    template<class T, class U>
    struct Foo {};
    
    #include <type_traits>
    
    template<template<class...> class T, class U>
    struct is_template_of
    {
        template<class... TT>
        static std::true_type test(T<TT...>*);
    
        static std::false_type test(...);
    
        constexpr static bool value = decltype(test((U*)nullptr)){};
    };
    
    template<template<class...> class T, class...>
    struct is_template_of_N : std::true_type
    {};
    
    template<template<class...> class T, class U, class... TT>
    struct is_template_of_N<T, U, TT...>
        : std::integral_constant<bool,    is_template_of<T,U>::value
                                       && is_template_of_N<T, TT...>{}>
    {};
    
    template<typename... Arguments>
    class VariadicTemplate
    {
        static_assert(is_template_of_N<Foo, Arguments...>{},
                      "a meaningful error message");
    };
    
    int main()
    {
        VariadicTemplate<Foo<int, double>, Foo<int, int>> v0; (void)v0;
        VariadicTemplate<Foo<int, double>, int> v1; (void)v1;
    }
    
    0 讨论(0)
  • 2020-12-19 15:46

    Here there is anothe solution :P

    Here it is:

    template <bool... b> struct static_all_of;
    
    // do recursion if the first argument is true
    template <bool... tail>
    struct static_all_of<true, tail...> : static_all_of<tail...> {};
    
    // end recursion if first argument is false
    template <bool... tail>
    struct static_all_of<false, tail...> : std::false_type {};
    
    // end recursion if no more arguments need to be processed
    template <> struct static_all_of<> : std::true_type {};
    
    
    // First template argument is given as the type checking for the is_base_of() function
    
    template <typename Type, typename... Requirements>
    class CollectionOfCommonBase : public Requirements...
    {
      static_assert(static_all_of<std::is_base_of<Type, Requirements>::value...>::value, "One or more template arguments are not base_of the one specified - given template specialization is not allowed.");
    };
    

    So you got it working for:

    class Foo {};
    
    class AFoo : public Foo {};
    class BFoo : public Foo {};
    
    class MyCollection : public CollectionOfCommonBase<Foo, AFoo, BFoo> {};
    
    0 讨论(0)
  • 2020-12-19 15:56

    If you want to check the types (not inquiring about base types):

    #include <type_traits>
    
    template <typename ...>
    struct are_same : std::true_type {};
    
    template <typename S, typename T, typename ... Ts>
    struct are_same <S, T, Ts...> : std::false_type {};
    
    template <typename T, typename ... Ts>
    struct are_same <T, T, Ts...> : are_same<T, Ts...> {};
    
    template <typename ... Ts>
    inline constexpr bool are_same_v = are_same<Ts...>::value;
    

    Handling your example problem:

    template <typename ... Foos>
    void Foo (Foos ... foos)
    {
        static_assert(are_same_v<int, Foos...>);
    }
    
    0 讨论(0)
提交回复
热议问题