
I never use the lambda expression because they can be very slow, but I thought it would be nice to support some generic "invokable" expressions so perhaps supporting a form of bind for macros, like this:
CHAOS_PP_EXPR(CHAOS_PP_REPEAT(3, CHAOS_PP_BIND(CHAOS_PP_CAT, T, _1)) // T0 T1 T2
I personally never use the lambda expressions either, though the speed is not usually a big issue (since I'm not usually generating huge things). However, I can't define _1 et al--at least permanently, and having a separate macro tends to make things clearer (mnemonic names, etc.) rather than more difficult.
The _1, _2, etc, are not macros, but instead are parsed by the invoker.
Now, I'm not sure if this scales to every scenario. And it is playing extremely fast and loose with hanging parenthesis. I haven't spent a great deal of time playing with it. But, this would be magic:
#define _0 ARG(0) #define _1 ARG(1)
APPLY( (A)(B), template<class T> class _0 : public _1 { public: inline _0(const _0& c) : _1(1, 2, 3) { // ... } }; )
#undef _0 #undef _1
If that can be made to work, that would be freakishly clever. You'd then have to do lambda bindings as another type of "control flag" to delay them (and hide the actual macros' names).
This seems really cool.
As well as supporting lambda or even user-defined invokable expressions. Ultimately, bind would just be implemented as this(Yes I know chaos already has a bind macro):
#define CHAOS_PP_BIND(m, ...) (CHAOS_PP_BIND)(m, __VA_ARGS__)
The library already allows what you pass to be a deferred expression in terms of NEXT(s). So you can put an arbitrary remapper:
#define MACRO(x, y) x - y #define DROP_AND_SWAP(s, y, x) (x, y)
CHAOS_PP_EXPR(CHAOS_PP_ENUM( 3, MACRO DROP_AND_SWAP, 3 ))
...contrived, I know.
I didn't realize deferred expression could be given, this seems to be a better way to approach the problem. You should really write a book on this.
A lot of this type of stuff is extremely trickly subject matter. A typical user isn't writing algorithms, etc.. They are just using the provided higher-level macros. What Chaos' does, for the most part, is take all implementation-level macros that could be useful as interfaces and define them as interfaces. I agree, however, that over-arching concepts, themes, idioms, and techniques need adequate documentation.
Where I got the term "parametric" from in this context I have no idea! Essentially, those algorithms process through from (e.g.) EXPR_1 through EXPR_10, but leave an extra EXPR_1, then jump back to EXPR_2, leave an extra EXPR_2, and so on. I.e. they use the recursion backend like this:
X X X X X X X X X X X X X X X
I.e. it is sort of a backend linear multiplier.
The _X macros use the backend in an exponential fashion--but those have some usability issues. I actually have a few combinations-of-both (i.e. _PARAMETRIC_X--whatever that means) algorithms laying around somewhere that are superior to the _X versions.
In both cases, however, these algorithms trade some speed for headroom. _PARAMETRIC is a little slower than normal, and _X is slower yet.
So the extra headroom can be used for the macro thats passed in, or for more repetitions, or both?