0

Microsoft Visual Studio Professional 2015 Version 14.0.25431.01 Update 3 issues errors when compiling the code below. Looks like a bug to me.


Thank you.

#include <iostream>

#define A( a, b, c, ... ) #__VA_ARGS__
#define B( ... ) A(__VA_ARGS__)

int main()
{
  // warning C4003: not enough actual parameters for macro 'A'
  // error C2059: syntax error: ';'
  std::cout << B( 1, 2, 3, 4 ); // should print '4'                                    
  return 0;
}
zdf
  • 4,382
  • 3
  • 18
  • 29

1 Answers1

2

It looks like a bug to me too. It's possible to work around it with another layer of macros:

#define EXPAND(...) __VA_ARGS__
#define A( a, b, c, ... ) #__VA_ARGS__
#define B( ... ) EXPAND(EXPAND(A) (__VA_ARGS__))

The idea is that first, EXPAND(A) gets expanded to A and (__VA_ARGS__) gets expanded to ( 1, 2, 3, 4 ). Then, you're left with A ( 1, 2, 3, 4 ), which VC++ understands if you force it to expand yet again.

  • 1
    I guess `#define EXPAND( a ) a` & `#define B( ... ) EXPAND(A(__VA_ARGS__))` is simpler. – zdf Dec 28 '16 at 17:27
  • @ZDF You do need `...` and `__VA_ARGS__` for `EXPAND` if you may want to pass it anything containing commas. As for `EXPAND(A(__VA_ARGS__))`, that should still try to expand `A(__VA_ARGS__)` first, and then expand the result again. If that is enough to suppress the warning, I think you've found another bug, and if *that* bug manages to get fixed before the original does, the code will break again. –  Dec 28 '16 at 17:32
  • I guess I did not find a thing. :) According to Microsoft, the behavior is the right one. See the [link](http://stackoverflow.com/questions/5134523/msvc-doesnt-expand-va-args-correctly) provided by cpplearner. – zdf Dec 28 '16 at 17:44
  • 1
    @ZDF Microsoft is wrong on this. They're conveniently ignoring [cpp.subst]p2, "An identifier `__VA_ARGS__` that occurs in the replacement list shall be treated as if it were a parameter, and the variable arguments shall form the preprocessing tokens used to replace it." Note the "as if it were a parameter". The replacement of parameters happens *before* the macro definition is expanded again, and commas contained therein can be used as macro argument separators. –  Dec 28 '16 at 17:50
  • I have filled a bug form at Microsoft Connect, but I doubt that they will change anything. It wouldn't be the first time. Thank you. – zdf Dec 28 '16 at 18:06