I definitely agree with that, but I think naming still needs some work. __THIS_MACRO__
appears to me to conflate two features; 1) the ability to name the current macro without knowing its name (often desired for generic code), and 2) the ability to recursively expand a macro.
Iām not convinced that this approach solves a substantial set of use cases for recursively expanded macros since it doesnāt support recursive expansion of a macro other than the current one. In other words, it canāt handle structural nesting operations. Consider the following example (which I hope I got right).
#define PROCESS_ELEM(X) X
#define PROCESS_LIST(...) __VA_OPT__(PROCESS(__VA_ARGS__))
#define PROCESS_NEXT(X, ...) PROCESS_##X __VA_OPT__(, PROCESS_NEXT(__VA_ARGS__))
#define PROCESS(X, ...) { PROCESS_##X __VA_OPT__(, PROCESS_NEXT(__VA_ARGS__)) }
struct S {
int dm1;
struct {
int dm1, dm2;
} dm2;
int dm3;
};
S s = PROCESS(ELEM(0), LIST(ELEM(1), ELEM(2)), ELEM(3));
The intent is that the last line expand to (ignoring white space concerns):
S s = { 0, { 1, 2 }, 3 };
The proposed __THIS_MACRO__
would suffice to allow recursion for the case where PROCESS_NEXT
recursively invokes itself, but it doesnāt suffice to address the case where PROCESS
is recursively invoked during the expansion of PROCESS_LIST
. A preprocessor operator that enables unconditional (recursive or non-recursive) expansion of the macro name it is applied to would suffice to address this use case.
Using @
as a placeholder for operator syntax, the macros above could then be defined as follows and would produce the intended output for the example above.
#define PROCESS_ELEM(X) X
#define PROCESS_LIST(...) __VA_OPT__(@PROCESS(__VA_ARGS__))
#define PROCESS_NEXT(X, ...) @PROCESS_##X __VA_OPT__(, @PROCESS_NEXT(__VA_ARGS__))
#define PROCESS(X, ...) { @PROCESS_##X __VA_OPT__(, @PROCESS_NEXT(__VA_ARGS__)) }