Boost logo

Boost :

From: Mat Marcus (mmarcus_at_[hidden])
Date: 2002-08-13 09:25:59

--On Monday, August 12, 2002 6:35 PM -0700 Andrei Alexandrescu
<andrewalex_at_[hidden]> wrote:

> "Terje Sletteb¯" <tslettebo_at_[hidden]> wrote in message
> news:153001c24071$34b897b0$60fb5dd5_at_pc...
>> Take one of the simplest algorithms, factorial.<
>> template<class V>
>> struct factorial
>> {
>> typedef typename V::type Value;
>> typedef typename apply_if<equal_to<Value,value<Value,0> >,
>> value<Value,1>,
>> mul<Value,factorial<prev<Value> > >
>> > ::type type;
>> }

> Besides, I frankly find the code abominable. It attempts to
> look and feel like runtime C++, and to me it doesn't do it.
> [I will snip the long explanation you provide for the
> *simplest* example, factorial, implemented in MPL. Using some
> of MPL. Using some not yet defined parts of MPL. Using some
> novel ideas of your own. Using a hard to follow syntax. I
> repeat, if that's the *simplest* example, we're really in bad
> shape here.]

First some meta-thoughts (regarding this discussion):

1) There is one thread about whether or not MPL's design
decision to offer multiple sequences is worth the cost. Paul
put a new spin on Andrei's old question whe he asked for two
real world examples: one where typelists are better than type
vectors and vice versa. Doug pointed out a possible example
where it might be more useful to work with type vectors. More
questions were raised about large sequences. Dave A. pointed
out some other uses for iterators. This thread appears to have
some "signal" left.

2) There is another sub-thread which is about metaprogramming
style. This is the raw pattern matching (specialization) versus
higher order metafunctional programming argument. This
which-is-truer-to-the-spirit-of-functional-programming part of
this argument is getting old, especially with the accompanying
rhetoric ("abominable", "really in bad shape", etc.). Not to
mention that we've been here before.

The answer to question 1 is not entirely clear to me. Regarding
2, I would allow for both styles. I find the writing of all the
specializations to be somewhat tedious, repetitive and error
prone. So I try to avoid them by using higher order
metafuntions such as fold. I believe that sometimes this can
result in more compact, readable code. A while ago onthis list
I tried rewriting Loki's GenLinearHierarchy using fold. It
looked something like this (untested):

template <class TList, class Glue, class Root = EmptyType>
struct GenLinearHierarchy {
    typedef boost::mpl::fold<TList, Root, Glue>::type type;

compare with the pattern matching style (from MC++D p. 72):

template <class TList, template <class AtomicType, class Base>
           class Glue, class Root = EmptyType>
class GenLinearHierarchy;

template <class T1, class T2, template <class, class> class
            class Root>
class GenLinearHierarchy<TypeList<T1,T2>, Glue, Root>
  : public Glue <T1, GenLinearHierarchy<T2, Glue, Root> >

template <class T, template <class, class> Glue, class Root>
class GenLinearHierarchy<TYPELIST_1(T), Glue, Root>
  : public Glue <T, Root>

The point is that I prefer not to write the template and the
two specializations. These specializations get repeated over
and over to detect the end of a type list. Higher order
metafunctions like fold abstract this repetition. This is not
to say that one should never pattern match. But I can't agree
that such code is "abominable". Nor is it relying on any
misguided analogies with runtime code, nor is it less
functional. Please express your opinions on these matters, but
let's tone down the rhetoric here.


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