Boost logo

Boost :

From: Terje Slettebø (tslettebo_at_[hidden])
Date: 2004-11-01 17:08:43


>From: "Vesa Karvonen" <vesa_karvonen_at_[hidden]>

> Lazy Metaprogramming Library

> This is a minimal proof-of-concept library that shows how one can
> implement lazy template metaprograms.
>
> Solution
> --------
>
> The metaprogramming style used in this library is different.
> Metafunctions and data structures (type lists) in this library are
> designed to be lazy. In particular, metafunctions assume that the
> arguments they receive are only delayed promises to compute the
> actual argument once explicitly invoked. This change of style
> eliminates the need to constantly think about evaluation order.

It's an interesting approach, and IIUC, one that has come up before (see the
"Meta function variants of mpl::apply_if necessary?" thread a couple of
years ago -
http://thread.gmane.org/gmane.comp.lib.boost.devel/73829). However, as shown
in the posting by Aleksey, it was considered and reconsidered during MPL
development, but dropped, due to not at least problems with passing nullary
metafunctions to functions, without evaluating them in the passing.

You might want to have a look at that thread (if you haven't), and see if
and how it relates to your proposal, and how your library addresses the
concerns there.

Your algorithms, such as:

template<class l>
struct SIEVE
  : CONS<HEAD<l>,
         SIEVE<FILTER<NOT_DIVISIBLE_BY<HEAD<l> >,
                      TAIL<l> > > > {};

look similar to my example in the above thread:

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<prior<Value> > >
>::type type;
}

The reason there are still "::type" expressions in the above, is that it
relies on MPL metafunctions that aren't lazy. However, factorial<> itself is
lazy, and that simplifies its design. Without it, you'd either need to split
it in two classes, to avoid over-eager evaluation and consequently infinite
compile-time recursion, or you'd need an eval<>/lazy<> construct that takes
a metafunction invocation and evaluates its arguments.

One argument I used was that having metafunctions "evaluate their own
arguments" follows the same way as run-time functions, which also evaluates
their own arguments, so to speak, implicitly.

One thing, though: Why the very non-Boost style identifiers (lower case
template parameters, and upper case template names), such as:

template<class t>
struct QUOTE {
  typedef t type;
};

Writing pp-code (using uppercase characters) a hard habit to break? ;)

Come to think of it, the "Generative Programming" book had the same
convention of upper case names for metafunctions.

Regards,

Terje


Boost list run by bdawes at acm.org, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk