Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Expand template type

Is there a way to convert each type of std::tuple into specific subtypes? I have following code

struct Foo1
{
    struct A{};
    struct B{};
};

struct Foo2
{
    struct A{};
    struct B{};
};

using myTypes = std::tuple<Foo1, Foo2>;

Is there a way to convert myTypes into following type?

std::tuple<Foo1::A, Foo1::B, Foo2::A, Foo2::B>;

Order of types doesn't matter, but would be nice to have it like above.

like image 273
konradk Avatar asked Aug 01 '26 21:08

konradk


2 Answers

If A/B name are fixed, you might do

template <typename... Ts>
using AB_Types = std::tuple<typename Ts::A..., typename Ts::B...>;

So AB_Types<Foo1, Foo2> is std::tuple<Foo1::A, Foo2::A, Foo1::B, Foo2::B>.

Having expected order would also be possible:

template <typename... Ts>
using AB_Types_ordered =
    decltype(std::tuple_cat(std::tuple<typename Ts::A, typename Ts::B>{}...));

and if source is a tuple, just add extra layer

template <typename>
struct AB_impl;

template <typename... Ts>
struct AB_impl<std::tuple<Ts...>>
{
    using type = AB_Types<Ts...>; // AB_Types_ordered<Ts...>
};

template <typename T>
using AB_Types_from_tuple = typename AB_impl<T>::type;
like image 109
Jarod42 Avatar answered Aug 04 '26 13:08

Jarod42


An alternative solution based on the Boost.Mp11 library:

template<class T>
using add_AB = std::tuple<typename T::A, typename T::B>;

template <typename Tuple>
using AB_Types_from_tuple = 
    boost::mp11::mp_flatten<boost::mp11::mp_transform<add_AB, Tuple>>;

static_assert(std::is_same_v<
    AB_Types_from_tuple<myTypes>,
    std::tuple<Foo1::A, Foo1::B, Foo2::A, Foo2::B>
>);
like image 32
Evg Avatar answered Aug 04 '26 13:08

Evg