Boost logo

Boost :

From: David Abrahams (dave_at_[hidden])
Date: 2002-12-31 07:55:58

"Jaap Suter" <J.Suter_at_[hidden]> writes:

>> Nifty! You're using one of my favorite metaprogramming tricks, the
>> default template parameter which allows you to avoid creating a
>> separate implementation template. I almost forgot about that one,
>> it's been so long since I've been able to use it.
> Funny you mention that. I've been meaning to ask for its appropriateness on
> this list. After all, we are exposing implementation details in the
> interface which is not something I would recommend on a daily basis. Glad
> you like it :).

That's a good point. It's a question of overall clarity. If it's
clearer to dispatch to an implementation template, I would say "do

>> > By the way, would it be worthwhile to create an 'Effective MPL' wiki
>> > page with some common gotchas on the different compilers? We could
>> > refer to the document on Integral Constant Expressions, we could
>> > mention the 'early template instantiation' and the work-around, and
>> > we could mention the lambda complications. And I'm sure that you and
>> > Dave have more gold nuggets from your experience using the MPL in
>> > real-world code.
>> Yes, it would probably be very worthwhile.
> I quickly hacked something together at:
> It still has some questions for you and Alexsey, and also some TODO's. I'll
> try to fill those in asap, probably next year :). Also, any comments or
> pointing out blatant errors (hej, I'm just an MPL newbie) would be greatly
> appreciated (or just fix them in the wiki directly).

Wow, that's great!

First thing to note is that you leave out "typename" all over the
place. Try testing your examples with GCC-3.2.

Second thing: you can save yourself lots of typenames by taking
advantage of the way MPL lets you pass an uninstantiated metafunction,
without getting its nested ::type member, wherever a bool_c<...> is

             typename equal_to<N, integral_c<N::value_type, 0> >::type
             , ...

can be written:

             equal_to<N, integral_c<N::value_type, 0> >
             , ...

Oh, your foo example seems to have too many "integral_c<"s in it:

  template< typename N >
  struct foo
    typedef apply_if< equal_to< N, integral_c< N::value_type, 0 > >::type,
                      foo< minus< N, integral_c< N::value_type, 1 > >::type >,
                      integral_c< integral_c< N::value_type, 0 >
>::type type;

One more hint you should use as an item: "Use inheritance to forward
metafunction results". So:

  template< typename N >
  struct foo
    typedef typename apply_if<
         equal_to< N, integral_c< N::value_type, 0 > >
         , foo<typename minus<N, integral_c<N::value_type, 1> >::type>
         , integral_c< N::value_type, 0 >
>::type type;

can be rewritten as:

  template<typename N>
  struct foo
      : apply_if<
           equal_to< N, integral_c< N::value_type, 0 > >
           , foo<typename minus<N, integral_c<N::value_type, 1> >::type>
           , integral_c<N::value_type, 0>

Lastly, I know that Aleksey will argue with me about this, but I have
a strong preference for "class" rather than "typename" in template
parameter lists. Aside from the fact that it's longer, "typename" is
visually confusable because it can mean other multiple things when it
appears between <...>:

   template <typename T, typename U = typename metafunction<T>::type>


   template <class T, class U = typename metafunction<T>::type>

Of course it also appears between <...> in other contexts. "class" is
never used that way unless it means "template type parameter". I
personally don't believe the use of "typename" for that purpose has
any value beyond pedantry.

                       David Abrahams
   dave_at_[hidden] *
Boost support, enhancements, training, and commercial distribution

Boost list run by bdawes at, gregod at, cpdaniel at, john at