Is it legal to invoke a variadic macro M
with no arguments for its variadic parameter?
The relevant standard quote is [cpp.replace]/4:
If the identifier-list in the macro definition does not end with an ellipsis, the number of arguments (including those arguments consisting of no preprocessing tokens) in an invocation of a function-like macro shall equal the number of parameters in the macro definition. Otherwise, there shall be more arguments in the invocation than there are parameters in the macro definition (excluding the
...
). There shall exist a)
preprocessing token that terminates the invocation.
For the case with no non-variadic parameters, an invocation in the form M()
should be legal as the invocation has one argument (consisting of no preprocessing tokens). So there is one more argument than non-variadic parameters.
For the case with one non-variadic parameter, should there be a trailing ,
as in M(1,)
to introduce an argument consisting of no preprocessing tokens for the variadic parameter? Otherwise, the number of arguments would be equal to the number of non-variadic parameters. i.e.,
#define variadic(x,...) #__VA_ARGS__
variadic(1,) // 2 arguments: ok
variadic(1) // 1 argument: wrong?
Both Clang and GCC, however, accept the following test case:
#include <iostream>
#define variadic(x,...) #__VA_ARGS__
int main()
{
std::cout << "'" variadic(1) "'" << std::endl;
}
and produce as output:
''
Is this non-standard behavior?
In C programming, a variadic function adds flexibility to the program. It takes one fixed argument and then any number of arguments can be passed. The variadic function consists of at least one fixed variable and then an ellipsis(…) as the last parameter. This enables access to variadic function arguments.
A comma must separate each parameter. For portability, you should not have more than 31 parameters for a macro. The parameter list may end with an ellipsis (…).
Preprocessor: __VA_ARGS__ (Variadic macros) If the parameters of a macro contain three consecutive dots ( ... ), this indicates that an arbitrary number of parameters may be passed. In the macro expansion, these values that are then referenced by the special identifier __VA_ARGS__ .
The double-number-sign or token-pasting operator (##), which is sometimes called the merging or combining operator, is used in both object-like and function-like macros. It permits separate tokens to be joined into a single token, and therefore, can't be the first or last token in the macro definition.
Otherwise, there shall be more arguments in the invocation than there are parameters in the macro definition (excluding the ...).
This very extract from the standard shows that your code should not be valid: you have one parameter plus the ellipsis. If we follow the portion of the standard above, you should have at least two arguments. When you write varidadic(1)
, you just provide one argument. Your code is not valid.
By the way, clang produces a warning:
main.cpp:7:32: warning: must specify at least one argument for '...' parameter of variadic macro [-Wgnu]
std::cout << "'" variadic(1) "'" << std::endl;
And GCC also produces a warning:
main.cpp:7:32: warning: ISO C99 requires rest arguments to be used [enabled by default]
std::cout << "'" variadic(1) "'" << std::endl;
Since that may be a bother to the programmer, and since the programmer's intent is easy to guess, they both consider variadic(1)
is equivalent to variadic(1,)
.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With