37

I am working on a call macro,

#define CALL(f,...) FN(f)->call((ref(new LinkedList()), __VA_ARGS__))

which when called,

CALL(print,2,3,4,5);

adds 2 3 4 5 to the linked list (, is overloaded to do so) and calls print which expects a linked list which works as expected how ever there are some calls which do not require arguments,

CALL(HeapSize);

It still takes a linked list but an empty one, above does not work, I am trying to come up with a macro that woud work with either style?

EDIT: Digging throug gcc docs I found that adding ## before VA_ARGS removes the , when there are no arguments but with that I can not nest macros,

CALL(print,CALL(HeadSize));

this causes CALL not defined error how ever if I separate the the calls it works

Lundin
  • 195,001
  • 40
  • 254
  • 396
Hamza Yerlikaya
  • 49,047
  • 44
  • 147
  • 241
  • 1
    You can have `CALL` delegate to different macros depending on the number of arguments it is passed. I demonstrated how to do this [in an answer to another question](http://stackoverflow.com/questions/5355241/generating-function-declaration-using-a-macro-iteration/5355946#5355946). This does not require any implementation-specific hacks. – James McNellis May 05 '11 at 00:30
  • also see http://stackoverflow.com/questions/5588855/standard-alternative-to-gccs-va-args-trick – Richard Hansen Feb 09 '12 at 03:26
  • related blogpost: ["Detect empty macro arguments"](https://gustedt.wordpress.com/2010/06/08/detect-empty-macro-arguments/). – Luiz Martins Mar 09 '21 at 16:00

7 Answers7

30

As for the updated question, by the use of auxiliary macro VA_ARGS like the following, the arguments will be expanded as expected.

#define VA_ARGS(...) , ##__VA_ARGS__
#define CALL(f,...) FN(f)->call((ref(new LinkedList()) VA_ARGS(__VA_ARGS__)))
Qix - MONICA WAS MISTREATED
  • 14,451
  • 16
  • 82
  • 145
Ise Wisteria
  • 11,259
  • 2
  • 43
  • 26
  • P.S. This worked well in my case where I needed to add NULL at the end: #define blah(x,...) actual(a,b,c,## _VA_ARGS__,NULL) – Brad Oct 23 '12 at 19:15
  • 13
    I've always been using this trick until I discovered that in pedantic mode of gcc when compiling for C99 or even C11, this yields a warning. Well, not exactly this macro definition itself, but calling a variadic macro with a zero variadic part. Why, oh why didn't they allow it in C11 standard?! – Alexander Amelkin Feb 16 '17 at 10:52
  • 3
    `__VA_OPT__` will be your friend @AlexanderAmelkin – Richard Jun 09 '21 at 22:00
21

If you're using gcc/g++ there is a way:

#define CALL(f,...) FN(f)->call((ref(new LinkedList()), ## __VA_ARGS__))

From the fine manual:

[...] if the variable arguments are omitted or empty, the `##' operator causes the preprocessor to remove the comma before it.

So gcc has an extension/hack specifically for the problem you are facing.

mu is too short
  • 426,620
  • 70
  • 833
  • 800
7

__VA_OPT__ (c++2a) should be more reliable, eg: from http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2016/p0306r2.html

The canonical use case of VA_OPT is for an optional separator:

#define LOG(msg, ...) printf(msg __VA_OPT__(,) __VA_ARGS__)

Community
  • 1
  • 1
timotheecour
  • 3,104
  • 3
  • 26
  • 29
6

If you are using GCC, it has an extension to swallow up the comma preceding the __VA_ARGS__. See: http://gcc.gnu.org/onlinedocs/cpp/Variadic-Macros.html.

Scott Moonen
  • 738
  • 4
  • 8
  • Only because yours is more thorough. :) – Scott Moonen May 05 '11 at 00:28
  • 1
    And MSVC, even though not mentioned on their MSDN page, supports the same extension, making everybody's lives a little bit easier. – vanza May 05 '11 at 00:28
  • 5
    @vanza: Actually, MSVC does it for you "automatically" -- if you have the sequence `, __VA_ARGS__` in a macro and `__VA_ARGS__` is empty, it will automatically swallow (delete) the `,`. It also just ignores `##` if its between two tokens that can't be merged, so the gcc extension works by serendipity. – Chris Dodd Apr 18 '14 at 16:26
2

A common theme in these answers is that we need a GCC specific hack. One way is to use the token-paste ##__VAR_ARGS__, but pasted arguments are not macro expanded, which means that macros cannot be nested. But if you are going to do something GCC specific anyway, then why not use the old-fashioned GCC extension:

 #define VARARG_FOO(ZeroOrMoreArgs...) \
     printf("VARARG_FOO: " ZeroOrMoreArgs)

ZeroOrMoreArgs is simply replaced by all the arguments (if any), commas and all. This includes recursive macro expansion.

  • then VARARG_FOO() expands to printf("VARARG_FOO: ")
  • and VARARG_FOO("I iz %d", 42) expands to printf("VARARGFOO: " "I iz %d", 42)

Finally

 #define NEST_ME "I tawt I taw a puddy tat"
 VARARG_FOO("The evil one says %s", NEST_ME); 

will expand to

 printf("VARARG_FOO: " "The evil one says %s", "I tawt I taw a puddy tat");

Pros:

  • You can nest macro invocations, while having zero-or more aguments.

Cons:

  • The ##__VA_ARGS__ hack might be harmless in standard C programs in the case where they always have at least one comma. (I haven't thought about whether this is true or not).
  • According to @ScootMoonen the ##__VA_ARGS__ hack is an undocumented extension to MSVC.
Adrian Ratnapala
  • 5,485
  • 2
  • 29
  • 39
2

Simply make f part of the ..., and use a separate macro to extract the first argument where you need f.

R.. GitHub STOP HELPING ICE
  • 208,859
  • 35
  • 376
  • 711
0

Unfortunately this cannot be done. You will need to define a separate macro to do this call.

As you end up with invalid arguments when VA_ARGS is substituted with nothing you end up with a floating ,

#define CALL0(f) FN(f)->call((ref(new LinkedList())))
JProgrammer
  • 2,750
  • 2
  • 25
  • 36