Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

__VA_ARGS__ expansion using MSVC

I found a question showing how to overload macros based on the number of arguments : Overloading Macro on Number of Arguments

But as they say, it's not working using MSVC because MSVC expands __VA_ARGS__ into a single token instead of a list of arguments (arg1, arg2, arg3).

They point to another question where a work around is given : MSVC doesn't expand __VA_ARGS__ correctly But not explained at all, so I can't adapt it to my own case since I can't understand it.

Could you please explain how this workaround works ?

like image 210
Virus721 Avatar asked Sep 04 '15 13:09

Virus721


People also ask

What is __ Va_args __ C++?

macro expansion possible specifying __VA_ARGS__ The '...' in the parameter list represents the variadic data when the macro is invoked and the __VA_ARGS__ in the expansion represents the variadic data in the expansion of the macro. Variadic data is of the form of 1 or more preprocessor tokens separated by commas.

How to use variadic macro?

To use variadic macros, the ellipsis may be specified as the final formal argument in a macro definition, and the replacement identifier __VA_ARGS__ may be used in the definition to insert the extra arguments. __VA_ARGS__ is replaced by all of the arguments that match the ellipsis, including commas between them.

What is #__ Va_args __?

Preprocessor: __VA_ARGS__ : count arguments This is an attempt to define a few variadic macros that can be used to count the number of arguments given.


1 Answers

The workaround in question is this:

#define EXPAND( x ) x
#define F(x, ...) X = x and VA_ARGS = __VA_ARGS__
#define G(...) EXPAND( F(__VA_ARGS__) )

The idea is that given an existing variadic macro F():

#define F(x, ...) X = x and VA_ARGS = __VA_ARGS__

instead of writing your desired variadic wrapper macro as, in this case, ...

#define G(...) F(__VA_ARGS__)

... you write G() with use of the additional EXPAND() macro. The actual definition of F() is not the point, and in particular it doesn't matter for this example that macro expansion does not produce valid C code. Its purpose is to demonstrate the preprocessor's behavior with respect to macro arguments. Specifically, it shows that although MSVC expands __VA_ARGS__ to a single token in a variadic macro, that can be worked around by forcing a double expansion.

For example, using the workaround definition, the preprocessor first expands ...

G(1, 2, 3)

... to ...

EXPAND( F(1, 2, 3) )

... where the 1, 2, 3 is treated as a single token. That tokenization no longer matters when the preprocessor rescans for additional replacements, however: it sees the 1, 2, 3 as separate arguments to macro F(), and expands that as desired to produce the argument to macro EXPAND(), which just replaces it with itself.

If you think it odd that this works as intended, but the version without EXPAND() does not work (in MSVC), you are right.

like image 64
John Bollinger Avatar answered Sep 22 '22 13:09

John Bollinger