Как получить тип члена boost::mpl для заполнения

Скажем, есть два класса:

struct A
{
    using Key = int;
    using Value = char;
};

struct B
{
    using Key = char;
    using Value = float;
};

Я хочу использовать их типы членов для определения карты Fusion:

typedef boost::fusion::map
<
    boost::fusion::pair< int , char > ,
    boost::fusion::pair< char , float >
> desired_type;

Поэтому я решил использовать MPL-фолд для получения типа:

typedef boost::fusion::result_of::as_map< boost::mpl::fold
<
    boost::mpl::vector< A , B > ,

    boost::fusion::map< > ,

    boost::fusion::result_of::push_back
    <
        boost::mpl::_1 ,
        boost::fusion::result_of::make_pair
        <
            boost::mpl::_2 ::Key , boost::mpl::_2 ::Value
        >
    >
>::type >::type map_type;

Но, конечно, это не могло работать, так как boost::mpl::_N действительно метафункции, возвращающие N-й аргумент.

Итак, я определил две вспомогательные метафункции:

template< class T >
struct GetInnerKey
{
    typedef typename T::Key type;
};

template< class T >
struct GetInnerValue
{
    typedef typename T::Value type;
};

и правильно определил складку:

typedef boost::fusion::result_of::as_map< boost::mpl::fold
<
    boost::mpl::vector< A , B > ,

    boost::fusion::map< > ,

    boost::fusion::result_of::push_back
    <
        boost::mpl::_1 ,
        boost::fusion::result_of::make_pair
        <
            GetInnerKey< boost::mpl::_2 > , GetInnerValue< boost::mpl::_2 >
        >
    >
>::type >::type map_type;

( Жить в Колиру)

Мои вопросы:

  • Есть ли способ избавиться от GetInnerKey< > а также GetInnerValue< > используя что-то уже определенное в MPL или Fusion?

  • Есть ли способ избежать использования boost::fusion::result_of::as_map< >?

  • Это правильный подход для достижения моих целей?

1 ответ

Заполнители являются мета-функциями и должны использоваться с ленивой оценкой. ::type внутри заменителей _1 и _2 - это несколько сложных типов перед вычислением (вы можете проверить их по typeof (с g++)).

Так как класс A и B не являются мета-функциями, поэтому, вероятно, вам придется написать мета-функции для обработки взаимодействий с классом A и B.

например

template <class PT1, class... PTs>
struct map_type
{
    typedef typename map_type<PTs...>::type pts_map;
    typedef typename boost::fusion::result_of::as_map<
        boost::fusion::joint_view<
            boost::fusion::map<
                boost::fusion::pair< typename PT1::Key, typename PT1::Value>
            >,
            pts_map
        >
    >::type type;
};

template <class PT1>
struct map_type<PT1>
{
    typedef boost::fusion::map<
        boost::fusion::pair< typename PT1::Key, typename PT1::Value>
    > type;
};

Жить на Колиру

Другие вопросы по тегам