Background
I have some macros of the form ATTR(XXX(...)). ATTR processes XXX into a macro ATTR_IMPL_XXX(...), and XXX can have a variable number of arguments (these variadic args are just passed to another macro, and can be empty).
In the case there are no args for XXX, I would like to be able to use the macro XXX as an object-macro XXX (i.e. ATTR(XXX)), instead of having to add the unnecessary empty parens for the function-like XXX() (i.e. ATTR(XXX())). In this case, adding or removing the parens for XXX() should be completely equivalent in the final expansion.
Question
I would like to know how I can modify the macro ATTR in such a way that it will detect if XXX was passed in with or without parens, and add them to the expansion if they were not provided; i.e. it should process both XXX or XXX() into equivalent results.
Examples
Use Case
The following should be functionally equivalent:
ATTR(XXX)
ATTR(XXX())
// Both expand to: ATTR_IMPL_XXX()
I still need to be able to use the same macro with arguments:
ATTR(XXX(some, args))
// Expands to: ATTR_IMPL_XXX(some, args)
Sample Expansion
As per @EricPostpischil's comment:
#define ATTR(ARG) ATTR_IMPL_##ARG
#define ATTR_IMPL_XXX(...) /* whatever */
ATTR(XXX);
ATTR(XXX());
ATTR(XXX(1, 2, 3));
// Expansion:
// ATTR_IMPL_XXX();
// ATTR_IMPL_XXX();
// ATTR_IMPL_XXX(1, 2, 3);
Clarification
- I am not asking if I can use the macro
XXXdirectly with and without parens - I know this is not possible (see function-like macro with the same name as an object-like macro) - Adding more macros/levels of indirection to
ATTR(e.g. token pasting to detect no parens) is acceptable - Using a second object-like macro
#define XXX_NO_ARGS XXX()with another name is not acceptable - I am not asking how to use variadic macros, or macro arguments.
- This is not an X/Y problem, I simply want to know how/if I can use the macro name
XXXwithout parens, as an argument toATTR - I already have the macro working to translate
ATTR(XXX(...))toATTR_IMPL_XXX(...), as per (2) I am willing to modifyATTR
a ## b, but couldn't come up with anything myself. Also, I've been going through a lot of CPP libraries (likeboost,chaos_pp,cloak,cpp_magic), and seeing what they are able to achieve I find it quite likely that something is entirely within the realm of macro trickery.ATTR(XXX(...))toATTR_IMPL_XXX(...), as per (2) I am willing to modifyATTR.##, requires the result be a grammatical token, butATTR_IMPL_XXX(…)is multiple tokens": I'm not sure what you mean, the token-pasting operator is already working for me:#define ATTR(ARG) ATTR_IMPL_##ARGis what I already have, and It's doing exactly what I said. "The macro ATTR would receive XXX(…) as a single parameter, so it would have no way to process the XXX part separately from the (…) part": See my reply to Yunnosch, there may be a trick using##, to concatNULL_##XXX(...), and a#define NULL_XXX /* something */ATTR(XXX);orATTR(XXX,1,2,3). Then it would be possible to use C23__VA_OPT__to expand the former into some object-like macro and the latter into a function-like one with parameters. But as already mentioned, the specific identifierXXXcan't be both an object-like macro and a function-like macro at the same time.