Home > Software engineering >  Expand template type
Expand template type

Time:02-02

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.

CodePudding user response:

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;

CodePudding user response:

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>
>);
  • Related