Как объединить type и mpl :: vector в новый вектор - PullRequest
1 голос
/ 28 октября 2011

Я использую следующую конструкцию для создания вектора типов mpl.

struct Struct1{
    typedef int type;
};
struct Struct2{
    typedef float type;
};
template<typename T> struct TypeReader{
    typedef typename T::type type;
};

int main()
{
    typedef bm::vector<Struct1,Struct2> MPLVector;
    typedef bm::transform<MPLVector, TypeReader<bm::_1>>::type TypeList;
    static_assert(bm::equal<TypeList, bm::vector<int,float> >::value, "Is not same");
}

Пока это работает, как и ожидалось.Теперь я хотел бы сделать следующее:

struct Struct3{
    typedef bm::vector<char,double> type;
};
typedef bm::vector<Struct1,Struct2,Struct3> MPLVector;
typedef bm::transform<MPLVector, TypeReader<bm::_1>>::type TypeList;
static_assert(bm::equal<TypeList, bm::vector<int,float,char,double> >::value, "Is not same");

Это не работает.Итак, как мне нужно изменить структуру MetaFunction, чтобы она работала с обоими, только с typedef и mpl :: vector?
Или, если это невозможно, можно было бы сделать это, если я изменил все typedefs типа наmpl векторы?

Ответы [ 2 ]

2 голосов
/ 28 октября 2011

Я не думаю, что это возможно с mpl::transform, так как в результирующей последовательности потребуется сгенерировать несколько элементов из одного в исходной последовательности.Однако это можно сделать с помощью mpl::fold вместе со специализацией с mpl::is_sequence:

// Default case
template < typename Seq, typename TWrapper, typename Enable = void >
struct Flatten_imp
    : mpl::push_back< Seq, typename TWrapper::type >
{
};

// Sequence case
template < typename Seq, typename TWrapper >
struct Flatten_imp< 
    Seq,
    TWrapper, typename
    boost::enable_if< 
        mpl::is_sequence< typename 
            TWrapper::type 
        > 
    >::type
>   
{
    typedef mpl::joint_view< 
        Seq, typename 
        TWrapper::type 
    > type;
};

template < typename Seq >
struct Flatten
    : mpl::fold< Seq, mpl::vector<>, Flatten_imp< mpl::_, mpl::_ > >
{}

int main()
{
    typedef mpl::vector< Struct1, Struct2, Struct3 > MPLVector;
    typedef Flatten< MPLVector >::type TypeList;

    static_assert(
        mpl::equal<
            TypeList, 
            mpl::vector< int, float, char, double > 
        >::value, "Is not same");
}

Если вы хотите, чтобы выравнивание было рекурсивным, выможно вызвать Flatten в Flatten_impl, чтобы сгладить последовательность перед ее добавлением;однако, будьте осторожны, эта рекурсия будет работать, только если ваши последовательности содержат обертки, а не прямые типы, например

struct Struct3
{
    typedef mpl::vector< mpl::identity< char >, mpl::identity< double > > type;
}
0 голосов
/ 28 октября 2011

Вы должны будете специализировать TypeReader для случая, когда параметром является последовательность (вектор mpl, список слияния / вектор / кортеж);

В этом случае объедините мощность mpl::back_inserter с mpl::copy (для копирования из последовательности параметра в тип цели)

У меня нет времени для демонстрации. Для подсказок о том, как специализироваться для концепции последовательности, вы можете посмотреть на boost::enable_if. Тем не менее, ProofOfConcept можно легко сделать, просто специализируясь на template <typename> mpl::vector

...