1
votes

I use the following construct to create a mpl vector of types.

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");
}

So far this works as expected. Now what I would like to do is the following

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");

This does not work. So how do I need to change my MetaFunction struct that it will work with both, just a typedef and a mpl::vector?
Or if this is not possible would it be possible to do this if I change all type typedefs to mpl vectors?

2

2 Answers

2
votes

I don't think this is possible with mpl::transform, since it would need to generate several elements in the resulting sequence from a single one in the source sequence. However, this can be done with mpl::fold, along with specialization with 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");
}

If you want the flattening to be recursive, you can call Flatten in Flatten_impl to flatten the sequence before appending it; however, be careful that this recursion will only work if your sequences contain wrappers and not direct types, e.g.

struct Struct3
{
    typedef mpl::vector< mpl::identity< char >, mpl::identity< double > > type;
}
0
votes

You'd have to specialize TypeReader for the case where the parameter is a Sequence (mpl vector, fusion list/vector/tuple);

In that case combine the power of mpl::back_inserter with mpl::copy (to copy from the parameter's Sequence into the target type)

I don't currently have to time to demo this. For hints on how to specialize for the concept of a Sequence, you could look at boost::enable_if. However, a ProofOfConcept could easily be done by just specializing on template <typename> mpl::vector