Are Variadic macros nonstandard?
Quote Wikipedia:
Variable-argument macros were introduced in 1999 in the ISO/IEC 9899:1999 (C99) revision of the C language standard, and in 2011 in ISO/IEC 14882:2011 (C++11) revision of the C++ language standard.
So it's standard from C99 and C++11 onwards, but a GNU extension in C++03.
C99 compatible nested calls within variadic macros
macros overloading technique provides shortest code so far.
#define SEND_NO_ARG(obj, msg) find_method(obj, msg)(obj)
#define SEND_ARG(obj, msg, ...) find_method(obj, msg)(obj, __VA_ARGS__)
#define GET_18TH_ARG(arg1, arg2, arg3, arg4, arg5, \
arg6, arg7, arg8, arg9, arg10, arg11, arg12, arg13, \
arg14, arg15, arg16, arg17, arg18, ...) arg18
#define SEND_MACRO_SELECTOR(...) \
GET_18TH_ARG(__VA_ARGS__, \
SEND_ARG, SEND_ARG, SEND_ARG, SEND_ARG, SEND_ARG, \
SEND_ARG, SEND_ARG, SEND_ARG, SEND_ARG, SEND_ARG, \
SEND_ARG, SEND_ARG, SEND_ARG, SEND_ARG, SEND_ARG, \
SEND_NO_ARG, )
#define send(...) SEND_MACRO_SELECTOR(__VA_ARGS__)(__VA_ARGS__)
Variadic macro with no arguments for its variadic parameter
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,)
.
C variadic macro
According to : https://gcc.gnu.org/onlinedocs/cpp/Macro-Arguments.html
You can leave macro arguments empty; this is not an error to the
preprocessor (but many macros will then expand to invalid code). You
cannot leave out arguments entirely; if a macro takes two arguments,
there must be exactly one comma at the top level of its argument list.
Using MYTRACE_ERR(err,);
will compile!
Additionally the correct way of defining a variadic macro should be the following:
#define MYTRACE(fmt, ...) printf("%s(): "fmt"\n", __func__, ##__VA_ARGS__)
Cleaning up C/C++ code reveals problems with variadic macros
Use the gcc option -Wno-variadic-macros
to disable that particular warning.
Edit: (from comments)
To disable the warning for a section of code but leave it on in general, use #pragma GCC diagnostic
described here.
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wvariadic-macros"
// Your code and/or include files
// (No variadic warnings here)
#pragma GCC diagnostic pop
Variadic macros with zero arguments, and commas
No, because the macro invocation MAKE_TEMPLATE()
does not have zero arguments at all; it has one argument comprising zero tokens.
Older preprocessors, apparently including GCC at the time this answer was originally written, sometimes interpreted an empty argument list as you'd hope, but the consensus has moved toward a stricter, narrower extension which more closely conforms to the standard.
To get the answer below to work, define an additional macro parameter before the ellipsis:
#define MAKE_TEMPLATE(UNUSED, ...) template <typename T, ## __VA_ARGS__ >
and then always put a comma before the first argument when the list is not empty:
MAKE_TEMPLATE(, foo )
Old answer
According to http://gcc.gnu.org/onlinedocs/gcc/Variadic-Macros.html, GCC does support this, just not transparently.
Syntax is:
#define MAKE_TEMPLATE(...) template <typename T, ## __VA_ARGS__ >
Anyway, both also support variadic templates in C++0x mode, which is far preferable.
Related Topics
Opencv on MAC Is Not Opening Usb Web Camera
Gcc Can Compile a Variadic Template While Clang Cannot
Passing Constexpr Objects Around
Differencebetween Include_Directories and Target_Include_Directories in Cmake
What Is the Use of "Using Namespace Std"
Using Char16_T and Char32_T in I/O
C++, Std::Atomic, What Is Std::Memory_Order and How to Use Them
Passing Object by Reference in C++
How to Load & Call a Vbscript Function from Within C++
Why Does Sizeof(Int) Vary Across Different Operating Systems
How to Include Data Object Files (Images, etc.) in Program and Access the Symbols
Why Is My Double or Int Value Is Always 0 After Division
What Happens When I Assign a Number Larger Than Int_Max to an Int
What's the Point of Const Pointers
Should Every Class Have a Virtual Destructor
Open File with Fopen, Given Absolute Path on Windows
Std::Async Won't Spawn a New Thread When Return Value Is Not Stored