How to return a type that mapped to varidiac positoin

I’m enjoying learning about metaprogramming, and started find out about some features, I can’t make the call to at works which takes an index to return a type that mapped to varidiac positoin.

#include <iostream>
#include <type_traits>
#include <utility>
template <typename...>
struct type_list {};
template<typename T ,typename... Ns>
auto pop_front(type_list<T, Ns...>t) {
    return type_list<Ns...>{};
}
template<typename T ,typename... Ns>
auto front(type_list<T, Ns...>t) 
{
    return type_list<T>{};
}
template<typename T ,typename... Ns>
auto at(type_list<T, Ns...>t, size_t i)
{
    if (i) return at(pop_front(t), i-1);
    return front(t);
}

int main()
{
    type_list<int, bool, float> x;
    at(x,2);
}

>Solution :

If we move the index into the template paramters so that it becomes a compile time constant then we can leverage std::tuple_element to get the type at the supplied index like

template<size_t Idx, typename... Ts>
auto at(type_list<Ts...>)
{
    return std::tuple_element_t<Idx, std::tuple<Ts...>>{};
}

and then we can call it like

at<2>(x);

It should be noted that this approach requires all types in the list to be default constructible.


If you are only ever going to use at in a context like decltype(at<2>(x)) then you actually don’t need to define the function and can instead use what I call a "meta function" like

template<size_t Idx, typename... Ts>
auto at(type_list<Ts...>t) -> std::tuple_element_t<Idx, std::tuple<Ts...>>;

and now you can’t run this function, but you can use it an any unevaluated context, like in decltype(at<2>(x)), and the types in the list do not need to be default constructible.

Leave a Reply