FloriHe
FloriHe

Reputation: 73

Retrieve special type parameter of recursive variadic template

Is something like that possible:

#include <iostream>
#include <string>

template<typename T1, typename T2, typename T3, typename T4, class ...Ts>
struct third_t {

    typedef typename third_t<T2,T3,T4,Ts...>::type type;
};

template<typename T1,typename T2, typename T3>
struct third_t<T1,T2,T3,void> {

    typedef T3 type;
};

int main() {

    third_t<int,int,std::string,unsigned>::type z = "test";

    std::cout<<"string type: "<<z<<std::endl;
}

If yes, why isn't the specialized case found? I.e. it isn't even considered in the resolution.

I get the error:

main.cpp: In instantiation of 'struct third_t<int, int, std::__cxx11::basic_string<char>, unsigned int>':

main.cpp:18:46:   required from here

main.cpp:7:56: error: wrong number of template arguments (3, should be at least 4)

     typedef typename third_t<T2,T3,T4,Ts...>::type type;

update:

I realized that my initial false presumption led me to think that I could "overload" a class as well, which of course is nonsense. Whereas something like that can be done with function templates, that

template<typename T1,typename T2, typename T3>
struct third_t { ... };

cannot be done with class templates, if so it would have been possible to extract the third-last parameter out of the template parameters.

Upvotes: 1

Views: 70

Answers (1)

max66
max66

Reputation: 66230

why isn't the specialized case found?

Because there isn't a void in the end of the type list of

third_t<int,int,std::string,unsigned>::type z = "test";

If you try with

third_t<int,unsigned,int,std::string,void>::type z = "test";

compile.

-- EDIT --

The OP ask to get the third type using a "recorsive construction".

So I suggest the costruction of a type traits that get the n-th-type (where n is a template parameter) of a list of types.

Something like

template <std::size_t N, typename, typename ... Ts>
struct nth_t
 { using type = typename nth_t<N-1U, Ts...>::type; };

template <typename T0, typename ... Ts>
struct nth_t<0U, T0, Ts...>
 { using type = T0; };

So the third parameter can be found using the index 2U (as usual in C/C++, starting from 0U) as follows

nth_t<2U, int, int, std::string, void>::type z = "test";

Upvotes: 1

Related Questions