elgcom elgcom - 1 month ago 24
C++ Question

use the TYPE from the tempate type argument list

I would like to use the type information from a class template argument list.

Working example with quick workaround:

struct NoParam {};
template< typename A = NoParam,
typename B = NoParam,
typename C = NoParam,
typename D = NoParam,
typename E = NoParam,
typename F = NoParam >
struct TypeList
{
typedef A T1;
typedef B T2;
typedef C T3;
typedef D T4;
typedef E T5;
typedef F T6;
};

template<typename... Types>
class Application
{
Application()
{
// the actual code will store the created instances in a tuple or map..
std::make_unique< TypeList<Types...>::T1 > ();
std::make_unique< TypeList<Types...>::T2 > ();
std::make_unique< TypeList<Types...>::T3 > ();
std::make_unique< TypeList<Types...>::T4 > ();
std::make_unique< TypeList<Types...>::T5 > ();
std::make_unique< TypeList<Types...>::T6 > ();
}
}


Is there any generic way...


  • to iterate over Types and get the type info (for creating instances)

  • no hard coded for only limited 6 types in the example


Answer

Do not re-invent the wheel, you can use std::tuple and std::tuple_element_t for that:

template<typename... T>
using TypeList = std::tuple<T...>;

template<int I, typename T>
using Type = std::tuple_element_t<I, T>;

template<typename... Types>
class Application {
    Application() {
        std::make_unique<Type<0, TypeList<Types...>>> ();
        std::make_unique<Type<1, TypeList<Types...>>> ();
        // and so on...
    }
}

Iterate over the types is quite simple now.
It follow a minimal, working example to show you how you can do that:

#include <tuple>
#include <functional>
#include <memory>

template<typename... T>
using TypeList = std::tuple<T...>;

template<int I, typename T>
using Type = std::tuple_element_t<I, T>;

template<typename... Types>
class Application {
    using MyTypeList = TypeList<Types...>;

    template<std::size_t... I>
    void iterate(std::index_sequence<I...>) {
        // demonstration purposes, here I'm simply creating an object of the i-th type
        int _[] = { 0, (Type<I, MyTypeList>{}, 0)... };
        (void)_;
    }

public:
    void iterate() {
        iterate(std::make_index_sequence<sizeof...(Types)>{});
    }

    Application() {
        std::make_unique<Type<0, MyTypeList>> ();
        std::make_unique<Type<1, MyTypeList>> ();
        // and so on...  
    }
};

int main() {  
    Application<int, float> app;
    app.iterate();
}

Note that std::index_sequence and std::make_index_sequence are available since C++14. Anyway, you can find online several implementations to be used if you are constrained to C++11.
Otherwise, you can also iterate over the types with a couple of recursive _sfinae'd_functions that check if sizeof...(Types) has been reached.