c++c++17template-meta-programming

How to convert a tuple of types to a tuple of class template instantiations, using the tuple types as template arguments


Consider the following types.

template<int data_>
struct CompileTimeData{ static constexpr int data = data_; };

template<int data>
struct S{};

In C++17, how does one convert a tuple of different CompileTimeData instances into a tuple of different S instances? The data should be used as template argument for S.

std::tuple<CompileTimeData<4>, CompileTimeData<2>> ---> std::tuple<S<4>, S<2>>

In practice, CompileTimeData will have multiple integers as template parameters, each of which must be passed to S.

My use case would look like this:

template<class DataTupleA, class DataTupleB>
struct X{
   using TupleOfS_A = ... // convert from DataTupleA
   using TupleOfS_B = ... // convert from DataTupleB
};

X<
   std::tuple<CompileTimeData<4>, CompileTimeData<2>>,
   std::tuple<CompileTimeData<3>, CompileTimeData<5>>
> x;


Solution

  • You can create a traits for that:

    template <typename Tuple>
    struct myTransform;
    
    template <int... Ns>
    struct myTransform<std::tuple<CompileTimeData<Ns>...>>
    {
        using type = std::tuple<S<Ns>...>;
    };
    

    Demo

    You might have a more generic transform as follow:

    template <typename Tuple, template <typename> class Transformer>
    struct TupleTransform;
    
    template <typename... Ts, template <typename> class Transformer>
    struct TupleTransform<std::tuple<Ts...>, Transformer>
    {
        using type = std::tuple<typename Transformer<Ts>::type...>;
    };
    

    and then

    template <typename> struct CompileTimeData2S;
    
    template <int N/*, ..*/>
    struct CompileTimeData2S<CompileTimeData<N/*, ..*/>>
    {
        using type = S<N /*, ..*/>;
    };
    

    Demo