
From: "Vesa Karvonen" <vesa_karvonen@hotmail.com>
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