Boost logo

Boost Users :

From: Edward Diener (eldiener_at_[hidden])
Date: 2008-05-06 13:25:42


I am making another effort to understand MPL. I have the book by David
Abrahams and Aleksey Gurtovoy, "C++ Template Programming", which is my
basic source for learning the library, and I have the Boost
documentation for the MPL.

After reading chapter 3 again I think I understand the basic concepts
more easily. However I am still missing something basic, which I think
can be given the name:

"How do I understand when to append and when not to append the '::type'
to a metaprogramming construct built with MPL".

Let me first say that I fully understand that '::type' is the way that
the MPL returns compile time data in its metafunctions. Also that I
understand that '::type' may refer to compile time numeric data (
including bool ) in the eventual form of '::type::value' and that
'::value' is often supplied as a shorthand for compile time numeric
data. Finally I do understand that to pass metafunctions around when a
type is needed the MPL uses a metafunction class, which is a type and
not a template.

What I am missing is how to determine when using MPL functionality,
whether it be data types, sequences, iterators, algorithms, or views
being manipulated, when to append '::type' to the end of the
intermediary expression or not.

Let me give some examples of my confusion based on my reading in the MPL
book listed above. I am reading about algorithms and I see an example
whose logic I perfectly understand, and whose syntax goes like this:

template<class Seq>
struct biggest_float_as_double :
   mpl::deref
   <
     typename mpl::max_element
     <
       typename mpl::replace
       <
         Seq,
         float,
         double
>::type,
       mpl::less
       <
         mpl::sizeof_<_1>,
         mpl::sizeof_<_2>
>
>::type
>
{};

In two cases in the nested construct above one uses the 'typename
xxx<...>::type' construct whereas in one case one does not. There seems
to be some logic or rule about this but I do not understand what it is.

A few pages later in the text I see:

typedef mpl::vector
<
   mpl::vector_c<int, 1, 2, 3>,
   mpl::vector_c<int, 4, 5, 6>,
   mpl::vector_c<int, 7, 8, 9>
>
S;

typedef mpl::transform
<
   S,
   mpl::front<_>,
   mpl::inserter
   <
     mpl::int_<0>,
     mpl::plus<_,_>
>
>
::type sum;

Here we have another nested mpl construct and I do understand the logic
of it, but here there are no internal nested '::type' statements. Once
again I am utterly puzzled about the whys and wherefores of using or not
using '::type'.

Finally I turn the page and I see this MPL construct:

template<class Seq>
struct reverse :
   mpl::fold
   <
     Seq,
     typename mpl::clear<Seq>::type,
     mpl::push_front<_,_>
>
{};

Once again I can follow the logic and the explanation of mpl::fold, but
I have no idea by what rule one of the nested constructs has '::type'
appended and the next one does not.

As a naive learner of the MPL I would have thought it would have been
much easier to use if every MPL construct ( mpl::xxx... ) returned a
'::type', and then this business of when to use and when not to use
'::type' would have been regularized, but evidently MPL does not work
that way. Since I still do not understand the rule about this, hopefully
someone who knows MPL, and who realizes that while I understand the
basic concepts I am still trying to understand it, can enlighten me on
this subject.


Boost-users list run by williamkempf at hotmail.com, kalb at libertysoft.com, bjorn.karlsson at readsoft.com, gregod at cs.rpi.edu, wekempf at cox.net