I created a small macro metaprogramming library that implements basic useful constructs such as REPEAT(times, x)
, IF(value, true, false)
, tuples, and more.
Most of my implementations work by overloading macros based upon their variadic argument count or through a counter:
// Example:
#define REPEAT_0(x)
#define REPEAT_1(x) x REPEAT_0(x)
#define REPEAT_2(x) x REPEAT_1(x)
#define REPEAT_3(x) x REPEAT_2(x)
// ...
// (these defines are generated using an external script)
// ...
#define REPEAT(count, x) CAT(REPEAT_, count)(x)
This works fine, but I've recently come across an extremely interesting implementation of macro recursion by Paul Fultz.
Up until the deferred expression section I had no trouble understanding his article.
I am, however, having a lot of trouble understanding the use of DEFER
and OBSTRUCT
properly.
Paul implements a very elegant version of REPEAT
that does not require script-generated defines like this:
#define EAT(...)
#define EXPAND(...) __VA_ARGS__
#define WHEN(c) IF(c)(EXPAND, EAT)
#define REPEAT(count, macro, ...) \
WHEN(count) \
( \
OBSTRUCT(REPEAT_INDIRECT) () \
( \
DEC(count), macro, __VA_ARGS__ \
) \
OBSTRUCT(macro) \
( \
DEC(count), __VA_ARGS__ \
) \
)
#define REPEAT_INDIRECT() REPEAT
//An example of using this macro
#define M(i, _) i
EVAL(REPEAT(8, M, ~)) // 0 1 2 3 4 5 6 7
DEFER
, OBSTRUCT
and other utilities are implemented as such:
#define EMPTY()
#define DEFER(id) id EMPTY()
#define OBSTRUCT(...) __VA_ARGS__ DEFER(EMPTY)()
#define EXPAND(...) __VA_ARGS__
#define A() 123
A() // Expands to 123
DEFER(A)() // Expands to A () because it requires one more scan to fully expand
EXPAND(DEFER(A)()) // Expands to 123, because the EXPAND macro forces another scan
-
When the preprocessor expands a macro, the result is "painted" until the next scan - it will not expand recursively unless an additional scan occurs. Is this correct?
-
Does the
EXPAND(...)
macro force an additional scan? If so, does this scan allow macros to expand recursively? What's the difference btweenEXPAND(...)
andDEFER(id)
?- Does
DEFER
force two additional scans?
- Does
-
What about the
OBSTRUCT(...)
macro? Does it force two additional scans? -
Now - why is
OBSTRUCT
required in the recursive implementation ofREPEAT
? Why wouldn'tDEFER
orEXPAND
work here?
Aucun commentaire:
Enregistrer un commentaire