MSVC doesn't expand __VA_ARGS__ correctly

Visual C++C PreprocessorVariadic Macros

Visual C++ Problem Overview


Consider this code:

#define F(x, ...) X = x and VA_ARGS = __VA_ARGS__
#define G(...) F(__VA_ARGS__)
F(1, 2, 3)
G(1, 2, 3)

The expected output is X = 1 and VA_ARGS = 2, 3 for both macros, and that's what I'm getting with GCC, however, MSVC expands this as:

X = 1 and VA_ARGS = 2, 3
X = 1, 2, 3 and VA_ARGS =

That is, __VA_ARGS__ is expanded as a single argument, instead of being broken down to multiple ones.

Any way around this?

Visual C++ Solutions


Solution 1 - Visual C++

Edit: This issue might be resolved by using /Zc:preprocessor or /experimental:preprocessor option in recent MSVC. For the details, please see here.

MSVC's preprocessor seems to behave quite differently from the standard specification.
Probably the following workaround will help:

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

Solution 2 - Visual C++

I posted the following Microsoft support issue:

> The following program gives compilation error because the precompiler > expands __VA_ARGS__ incorrectly: > > #include >
> #define A2(a1, a2) ((a1)+(a2)) >
> #define A_VA(...) A2(VA_ARGS) >
> int main(int argc, char *argv[]) > { > printf("%d\n", A_VA(1, 2)); > return 0; > } > > The preprocessor expands the printf to: > printf("%d\n", ((1, 2)+())); > > instead of > printf("%d\n", ((1)+(2)));

I received the following unsatisfying answer from a Microsoft compiler team developer:

> Hi: The Visual C++ compiler is behaving correctly in this case. If you combine the rule that tokens that match the '...' at the inital macro invocation are combined to form a single entity (16.3/p12) with the rule that sub-macros are expanded before argument replacement (16.3.1/p1) then in this case the compiler believes that A2 is invoked with a single argument: hence the error message.

Solution 3 - Visual C++

What version of MSVC are you using? You will need Visual C++ 2010.

__VA_ARGS__ was first introduced by C99. MSVC never attempted to support C99, so the support was not added.

Now, however, __VA_ARGS__ is included in the new C++ standard, C++2011 (previously known as C++0x), which Microsoft apparently plans to support, so it has been supported in recent versions of MSVC.

BTW, you will need to use a .cpp suffix to your source file to get this support. MSVC hasn't updated its C frontend for a long time.

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
Questionuj2View Question on Stackoverflow
Solution 1 - Visual C++Ise WisteriaView Answer on Stackoverflow
Solution 2 - Visual C++dmitryvolkView Answer on Stackoverflow
Solution 3 - Visual C++chysView Answer on Stackoverflow