5

Consider the following code (live example):

#define TEST_VA(mX, ...) TEST
#define STRINGIFY_IMPL(mX) #mX
#define STRINGIFY(mX) STRINGIFY_IMPL(mX)

#include <iostream>

int main()
{
    std::cout << STRINGIFY(TEST_VA(1)) << std::endl;
    std::cout << STRINGIFY(TEST_VA()) << std::endl;
    return 0;
}

clang++ 3.4 complains:

main.cpp:9:37: warning: must specify at least one argument for '...' parameter of variadic macro [-Wgnu-zero-variadic-macro-arguments]
    std::cout << STRINGIFY(TEST_VA(1)) << std::endl;
                                    ^
main.cpp:1:9: note: macro 'TEST_VA' defined here
#define TEST_VA(mX, ...) TEST
        ^
main.cpp:10:33: warning: must specify at least one argument for '...' parameter of variadic macro [-Wgnu-zero-variadic-macro-arguments]
        std::cout << STRINGIFY(TEST_VA()) << std::endl;
                                       ^
main.cpp:1:9: note: macro 'TEST_VA' defined here
#define TEST_VA(mX, ...) TEST

I use some variadic macros like in the example code in my projects.

Is it safe to pass no arguments for the ... parameter of variadic macros? (Ignoring the warning, basically)

Or could it lead to problems?

Is it explicitly forbidden by the standard?

a3f
  • 8,517
  • 1
  • 41
  • 46
Vittorio Romeo
  • 90,666
  • 33
  • 258
  • 416
  • @FrançoisMoisan The [working standard draft](http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2012/n3337.pdf) contains sections relative to macros and preprocessing. – Vittorio Romeo Jan 21 '14 at 18:51

2 Answers2

3

Starting from C++20, passing zero arguments to a variadic macro parameter is allowed, but Clang (at least Clang 12) doesn't respect this change yet.

So if you're targeting C++20 or newer and using -pedantic-errors, then -Wno-gnu-zero-variadic-macro-arguments is recommended.


[cpp.replace.general]/5

... there shall be at least as many arguments in the invocation as there are parameters in the macro definition (excluding the ...).

HolyBlackCat
  • 78,603
  • 9
  • 131
  • 207
2

It's technically forbidden by the standard. From C++11 §16.3/4 (emphasis added):

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.

Some compilers may allow this as an extension, but if you want standards-compliant code, you should make sure to always include at least one argument for the ellipsis parameter of a variadic macro.

Adam Rosenfield
  • 390,455
  • 97
  • 512
  • 589
  • I'm relying on zero-arguments variadic macros for compile time preprocessor recursion (foreach, tuples). Is there a workaround? – Vittorio Romeo Jan 21 '14 at 19:06
  • @VittorioRomeo: That obviously depends on what exactly you're trying to do. I personally wouldn't recommend trying to do such complicated things with the C preprocessor; if you really need to do that, you could try using a different, more flexible preprocessor instead, such as GNU m4 or a custom script. Using tools like that wouldn't be too hard to integrate into a Makefile-based build system, but it would make your build system more brittle and difficult to work with. – Adam Rosenfield Jan 21 '14 at 19:13
  • A basic example is countin variadic arguments. Seems like [boost has my same issue](http://www.boost.org/doc/libs/1_49_0/boost/preprocessor/variadic/size.hpp) – Vittorio Romeo Jan 22 '14 at 09:13