Получение списка типов членов из адаптированной структуры boost fusion

У меня есть адаптированные структуры boost fusion, подобные этой:

struct A {
    int x;
    double y;
    std::string z;
};
BOOST_FUSION_ADAPT_STRUCT(
    A,
    x,
    y,
    z
)

Я хотел бы перебрать типы адаптации во время компиляции. Например. если у меня есть класс, который обертывает тип:

template <typename T> class Foo { ... };

тогда я хотел бы иметь возможность получить тип std::tuple<Foo<int>, Foo<double>, Foo<std::string>> с учетом моей структуры A. Я использую здесь std::tuple просто в качестве примера; это может быть другой класс шаблона вариативного типа.

Решение С++ 17 приветствуется.


person Vladimir    schedule 24.10.2019    source источник


Ответы (1)


Помощник для преобразования адаптированной структуры слияния во что-то вроде std::tuple:

template<class Adapted, template<class ...> class Tuple = std::tuple>
struct AdaptedToTupleImpl
{
    using Size = boost::fusion::result_of::size<Adapted>;

    template<size_t ...Indices>
    static Tuple<typename boost::fusion::result_of::value_at_c<Adapted, Indices>::type...> 
        Helper(std::index_sequence<Indices...>);

    using type = decltype(Helper(std::make_index_sequence<Size::value>()));
};

template<class Adapted, template<class ...> class Tuple = std::tuple>
using AdaptedToTuple = typename AdaptedToTupleImpl<Adapted, Tuple>::type;

Проверка:

using AsTuple = AdaptedToTuple<A>;
static_assert(std::is_same_v<std::tuple<int, double, std::string>, AsTuple>);

Помощник, который применяет метафункцию к каждому типу в кортеже:

template<class List, template<class> class Func> struct ForEachImpl;

template<class ...Types, template<class ...> class List, template<class> class Func>
struct ForEachImpl<List<Types...>, Func>
{
    using type = List<Func<Types>...>;
};

template<class List, template<class> class Func>
using ForEach = typename ForEachImpl<List, Func>::type;

Проверка:

static_assert(std::is_same_v<ForEach<AsTuple, std::add_pointer_t>, std::tuple<int*, double*, std::string*>>);

Также взгляните на библиотеку Boost.MP11. Он имеет метафункцию mp_transform, которая эквивалентна функции ForEach, описанной выше.

person pure cuteness    schedule 05.12.2019