MSVC doesn't expand __VA_ARGS__ correctly
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?
Solution 1:
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:
I posted the following Microsoft support issue:
The following program gives compilation error because the precompiler expands
__VA_ARGS__
incorrectly:#include <stdio.h> #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.