eci eci - 8 months ago 51
C++ Question

Boost mpl transformed sequence "real" type

See the following code from the boost mpl transform documentation:

typedef vector<char,short,int,long,float,double> types;
typedef vector<char*,short*,int*,long*,float*,double*> pointers;
typedef transform< types,boost::add_pointer<_1> >::type result;
BOOST_STATIC_ASSERT(( equal<result,pointers>::value ));

I want to understand the type system of
and "how it actually works".
As I understand
just compares the elements of the following two sequences and not the whole sequence types themselves.
I do not understand why the following fails:

BOOST_STATIC_ASSERT(( std::is_same<result,pointers>::value )); //< assert fails

Why is the result type not 100% identical to the "pointers" type?
I assume that is somehow because mpl is performing the transformation lazy or the result is just a sequence and not a vector any more?
Is it possible to somehow force mpl to do not being lazy any more and get the 100% identical type (I could write a transform function myself with this result, but i want to know how to do it in mpl)?

I tried already some things like e.g. inserting the result in a new vector but without success:

BOOST_STATIC_ASSERT(( std::is_same<
mpl::insert_range< mpl::vector<>, mpl::begin<mpl::vector<> >::type,
result >::type, pointers >::value )); //< assert fails too

Also, i tried using a back_insert in the transformation function, which fails too:

typedef transform< types,boost::add_pointer<_1>,
mpl::back_inserter< mpl::vector< > > >::type result_new;
BOOST_STATIC_ASSERT(( std::is_same<result_new,pointers>::value )); //< fails...

Reading the "documentation" did not help me.
So again, is it possible to get the 100% identical type with mpl transform (or any other transforming sequence functions)? And what is the result of the type


"in reality" when it not is_same with pointers?

eci eci

Thanks again to @llonesmiz for the code to pretty print the types using typeid(), which helped to understand whats happening.

So it seems the real result type depends on the compiler (probably boost #ifdefs), intel compiler and visual studio convert it back to std::vectorN<> where the maximum N is a predefined number in boost (so it does not work when N is too large). For g++ a mangled type is generated (even 2 different types from my transform calls).

So i guess checking the type via mpl::equal is fine (check the elements of the ranges). If all types should be "really" equivalent (std::is_same holds) i guess you need to convert the result manually to a variadic template class std::tuple.

See$16 Code Sample

or in short:

template < class T, class R >
struct ToStdTuple;

template < class... TTypes, class X >
struct ToStdTuple< std::tuple< TTypes... >, X >
  typedef std::tuple< TTypes..., X > type;

and then

// typedef mpl::vector<char,short,int,long,float,double> types;
// typedef mpl::transform< types,boost::add_pointer<mpl::_1> >::type result;

typedef mpl::fold< result, std::tuple<>,
  ToStdTuple< mpl::_1, mpl::_2 > >::type result_normalized;

resulting in

std::tuple<char*, short*, int*, long*, float*, double*>

for all transformation calls