Reputation: 2412
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 boost::mpl
and "how it actually works".
As I understand mpl::equal
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
result
"in reality" when it not is_same with pointers?
Upvotes: 4
Views: 1194
Reputation: 2412
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 http://liveworkspace.org/code/3l8O9K$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
Upvotes: 7