If we define a macro
#define M(x, ...) { x, __VA_ARGS__ }
and then use it passing itself as an argument
M(M(1, 2), M(3, 4), M(5, 6))
then it expands to the expected form:
{ { 1, 2 }, { 3, 4 }, { 5, 6 } }
However, when we use the ##
operator (to prevent dangling comma from appearing in the output in the case of the single argument invocations, as documented in the GCC manual), i.e.
#define M0(x, ...) { x, ## __VA_ARGS__ }
then the expansion of arguments in
M0(M0(1,2), M0(3,4), M0(5,6))
seems to stop after the first argument, i.e. we get:
{ { 1,2 }, M0(3,4), M0(5,6) }
Is this behavior a bug, or does it stem from some principle?
(I have also checked it with clang, and it behaves in the same way as GCC)
Way down at the end of this answer there is a possible solution.
Is this behavior a bug, or does it stem from some principle?
It stems from two principles whose interaction is pretty subtle. So I agree that it is surprising, but it's not a bug.
The two principles are the following:
Inside the replacement of macro invocation, that macro is not expanded. (See the GCC Manual Section 3.10.5, Self-Referential Macros or the C Standard, §6.10.3.4 paragraph 2.) This precludes recursive macro expansion, which in most cases would produce infinite recursion if allowed. Although it is likely that no-one anticipated such uses, it turns out that there would be ways of using recursive macro expansion which would not result in infinite recursion (see the Boost Preprocessor Library documentation for a thorough discussion of this issue), but the standard isn't going to get changed now.
If ##
is applied to a macro argument, it suppresses macro expansion of that argument. (See the GCC Manual section 3.5, Concatenation or the C Standard, §6.10.3.3 paragraph 2.) The suppression of expansion is part of the C Standard, but GCC/Clang's extension to allow use of ##
to conditionally suppress the comma preceding __VA_ARGS__
is non-standard. (See the GCC Manual Section 3.6, Variadic Macros.) Apparently, the extension still respects the standard's rule about not expanding concatenated macro arguments.
Now, the curious thing about the second point, with respect to optional comma suppression, is that you hardly ever notice it in practice. You can use ##
to conditionally suppress commas and arguments will still get expanded as normal:
#define SHOW_ARGS(arg1, ...) Arguments are (arg1, ##__VA_ARGS__)
#define DOUBLE(a) (2 * a)
SHOW_ARGS(DOUBLE(2))
SHOW_ARGS(DOUBLE(2), DOUBLE(3))
This expands to:
Arguments are ((2 * 2))
Arguments are ((2 * 2), (2 * 3))
Both DOUBLE(2)
and DOUBLE(3)
are expanded normally, despite the fact that one of them is an argument to the concatenation operator.
But there's a subtlety to macro expansion. Expansion happens twice:
First, macro arguments are expanded. (This expansion is in the context of the text which invokes the macro.) These expanded arguments are substituted for the parameters in the macro replacement body (but only where the parameter is not an argument to #
or ##
).
Then the #
and ##
operators are applied to the replacement token list.
Finally, the resulting replacement tokens are inserted into the input stream, so that they are expanded again. This time, the expansion is in the context of the macro so recursive invocation is suppressed.
With that in mind, we see that in SHOW_ARGS(DOUBLE(2), DOUBLE(3))
, DOUBLE(2)
is expanded in step 1, before being inserted into the replacement token list, and DOUBLE(3)
is expanded in step 3, as part of the replacement token list.
This doesn't make a difference with DOUBLE
inside SHOW_ARGS
, since they're different macros. But the difference would become apparent if they were the same macro.
To see the difference, consider the following macro:
#define INVOKE(A, ...) A(__VA_ARGS__)
That macro creates a macro invocation (or a function invocation, but here we're only interested in the case where it's a macro). That is, in turns INVOKE(X, Y)
into X(Y)
. (That's a simplification of a useful feature, where the named macro is actually invoked several times, possibly with slightly different arguments.)
That works fine with SHOW_ARGS
:
INVOKE(SHOW_ARGS, one arg)
⇒ Arguments are (one arg)
But if we try to INVOKE
the macro INVOKE
itself, we find that the ban on recursive invocation takes effect:
INVOKE(INVOKE, SHOW_ARGS, one arg)
⇒ INVOKE(SHOW_ARGS, one arg)
"Of course", we could expand INVOKE
as an argument to INVOKE
:
INVOKE(SHOW_ARGS, INVOKE(SHOW_ARGS, one arg))
⇒ Arguments are (Arguments are (one arg))
That works fine because there is no ##
inside INVOKE
, so expansion of the argument is not suppressed. But if the expansion of the argument had been suppressed, then the argument would be inserted into the macro body unexpanded, and then it would become a recursive expansion.
So that's what is going on in your example:
#define M0(x, ...) { x, ## __VA_ARGS__ }
M0(M0(1,2), M0(3,4), M0(5,6))
⇒ { { 1,2 }, M0(3,4), M0(5,6) }
Here, the first argument to the outer M0
, M0(1,2)
, is not used with ##
, so it is expanded as part of the invocation. The other two arguments are part of __VA_ARGS__
, which is used with ##
. Consequently, they are not expanded prior to being substituted into the macro's replacement list. But as part of the macro's replacement list, their expansion is suppressed by the no-recursive-macros rule.
You can easily work around that by defining two versions of the M0
macro, with the same contents but different names (as suggested in a comment to the OP):
#define M0(x, ...) { x, ## __VA_ARGS__ }
M0(M1(1,2), M1(3,4), M1(5,6))
⇒ { { 1,2 }, { 3,4 }, { 5,6 } }
But that's not very pleasant.
__VA_OPT__
C++2a will include a new feature designed specifically to assist with suppressing commas in variadic invocations: the __VA_OPT__
function-like macro. Inside a variadic macro expansion, __VA_OPT__(x)
expands to its argument provided that there is at least one token in the variadic arguments. But if __VA_ARGS__
expands to an empty token list, so does __VA_OPT__(x)
. Thus, __VA_OPT__(,)
can be used for conditional suppression of a comma just like the GCC ##
extension, but unlike ##
, it does not trigger suppression of macro expansion.
As an extension to the C standard, recent versions of GCC and Clang implement __VA_OPT__
for C as well as C++. (See the GCC Manual Section 3.6, Variadic Macros.) So if you're willing to rely on relatively recent compiler versions, there is a very clean solution:
#define M0(x, ...) { x __VA_OPT__(,) __VA_ARGS__ }
M0(M0(1,2), M0(3,4), M0(5,6))
⇒ { { 1 , 2 } , { 3 , 4 }, { 5 , 6 } }
You can see these examples on Godbolt
This question was originally closed as a duplicate of Variadic macros: expansion of pasted tokens but I don't think that answer is really adequate to this particular situation.