How to detect the first and the last argument in the variadic templates?

前端 未结 2 834
一整个雨季
一整个雨季 2020-12-14 19:09

How to detect the first and the last argument in the variadic templates?

For the 1st argument it is easy (just compare sizeof...(T) with 0), but is ther

相关标签:
2条回答
  • 2020-12-14 19:21

    Here's another set of code with a convenience function return_type that you could use to access any type at a specific index in a varadic template list ... you could then adapt the call to return_type so that you get the first and the last arguments (i.e., the first argument will be at 0, and the last argument will be at sizeof...(TypeList)):

    template<typename T>
    struct type_id_struct
    {
        typedef T type;
        T object_instance;
    };
    
    template<int N, typename... TypeList>
    struct reduce {};
    
    template<int N, typename T1, typename... TypeList>
    struct reduce<N, T1, TypeList...>
    {
        typedef typename reduce<N - 1, TypeList... >::type type;
    };
    
    template<typename T1, typename... TypeList>
    struct reduce<0, T1, TypeList...>
    {
        typedef T1 type;
    };
    
    //convenience function
    template<int N, typename... TypeList>
    type_id_struct<typename reduce<N, TypeList...>::type> return_type()
    {
            return type_id_struct<typename reduce<N, TypeList...>::type>();
    }
    

    Here's an example of using the convenience function return_type in actual code to determine the Nth template argument in a variadic template:

    int main()
    {
        auto type_returned = return_type<2, int, double, char>();
        std::cout << typeid(type_returned.object_instance).name() << std::endl;
    
        return 0;
    }
    

    In this case, since the int template argument to return_type is 2, you'll get the char type as the output. Any number over 2 will cause an overflow that will create a compile rather than runtime error. As noted, you could adapt it so that it's wrapped inside a function in a structure that will allow you to access the types in the variadic template for that specific structure instance using the sizeof...(TypeList) - 1 applied to an enum. For instance:

    template<typename... TypeList>
    struct an_object
    {
        enum { first = 0, last = (sizeof...(TypeList) - 1) };
    
        template<int N>
        auto wrapper() -> decltype(return_type<N, TypeList...>())
        {
                return return_type<N, TypeList...>();
        }
    };
    
    //...more code
    
    int main()
    {
        an_object<int, double, char> a;
    
        auto r_type1 = a.wrapper<an_object<int, double, char>::first>();
        std::cout << typeid(r_type1.object_instance).name() << std::endl;
    
        auto r_type2 = a.wrapper<an_object<int, double, char>::last>();
        std::cout << typeid(r_type2.object_instance).name() << std::endl;
    
        return 0;
    }
    
    0 讨论(0)
  • 2020-12-14 19:42

    I'm not positive if this is what you want. But here are two utilities named first and last that take variadic templates and typedef the first and last type respectively:

    #include <iostream>
    #include <typeinfo>
    
    template <class T1, class ...T>
    struct first
    {
        typedef T1 type;
    };
    
    template <class T1, class ...T>
    struct last
    {
        typedef typename last<T...>::type type;
    };
    
    template <class T1>
    struct last<T1>
    {
        typedef T1 type;
    };
    
    template <class ...T>
    struct A
    {
        typedef typename first<T...>::type first;
        typedef typename last<T...>::type  last;
    };
    
    struct B1 {};
    struct B2 {};
    struct B3 {};
    
    int main()
    {
        typedef A<B1, B2, B3> T;
        std::cout << typeid(T::first).name() << '\n';
        std::cout << typeid(T::last).name() << '\n';
    }
    
    0 讨论(0)
提交回复
热议问题