RedApe
RedApe

Reputation: 129

How to create std::tuple of subtypes from std::tuple of given typelist

I have a typelist in form of std::tuple

struct A { struct data_type {}; };
struct B { struct data_type {}; };
struct C { struct data_type {}; };
struct D { struct data_type {}; };
//etc

using my_typelist = std::tuple<A, B, C, D>;

And I what define variable of tuple, containing inner types. Something like this

std::tuple<A::data_type, B::data_type, C::data_type, D::data_type> data;

But straightforward solution does not work (https://ideone.com/c8a2FE):

#include <tuple>
#include <iostream>

struct A { using data_type = int; };
struct B { using data_type = char; };

// error: template argument for template type parameter must be a type
template < typename... Ts >
using cvt_2_data = std::tuple< Ts::data... >; 

void main()
{
    using my_typelist = std::tuple<A, B>;
    cvt_2_data<my_typelist> data;
    std::cout 
        << std::get<A::data_type>(data) << " "
        << std::get<B::data_type>(data) << std::endl;
}

I've also tried this, and more complicated approaches, but no such luck

std::tuple< (Ts::data)... >;
std::tuple< decltype(Ts)::data... >;

By the way, I need solution for C++17

Upvotes: 1

Views: 149

Answers (2)

songyuanyao
songyuanyao

Reputation: 172924

It seems you want to specify std::tuple<A, B> as template argument, and get the type std::tuple<A::data_type, B::data_type>. You can do it with helper template and specialization. E.g.

template < typename... Ts >
struct cvt_2_data_struct; 
template < typename... Ts >
struct cvt_2_data_struct<std::tuple<Ts...>> {
    using type = std::tuple< typename Ts::data_type... >; 
};

template < typename... Ts >
using cvt_2_data = typename cvt_2_data_struct<Ts...>::type;

LIVE

BTW: Note the usage of typename in typename Ts::data_type... and typename cvt_2_data_struct<Ts...>::type, it's used to tell that the dependent qualified name is type. See Where and why do I have to put the “template” and “typename” keywords?.

Upvotes: 3

Try using partial specialization of a class/struct template:

template < typename T >
struct cvt_2_data_struct {};
template < typename... Ts >
struct cvt_2_data_struct<std::tuple< Ts... >> {
    using type = std::tuple< typename Ts::data_type... >;
};

template < typename T >
using cvt_2_data = typename cvt_2_data_struct<T>::type;

Upvotes: 2

Related Questions