   VC++ macro fail
  From this sitehttp://groups.google.com/group/comp.std.c/browse_thread/thread/77ee8c8f92e4a3fb/346fc464319b1ee5I got the following code to get the number of arguments passed to a variadic macro:#define PP_NARG(...)PP_NARG_(__VA_ARGS__,PP_RSEQ_N())#define PP_NARG_(...)PP_ARG_N(__VA_ARGS__)#define PP_ARG_N( _1, _2, _3, _4, _5, _6, _7, _8, _9,_10,_11,_12,_13,_14,_15,_16,_17,_18,_19,_20,_21,_22,_23,_24,_25,_26,_27,_28,_29,_30,_31,_32,_33,_34,_35,_36,_37,_38,_39,_40,_41,_42,_43,_44,_45,_46,_47,_48,_49,_50,_51,_52,_53,_54,_55,_56,_57,_58,_59,_60,_61,_62,_63,N,...) N#define PP_RSEQ_N()63,62,61,60,   59,58,57,56,55,54,53,52,51,50,49,48,47,46,45,44,43,42,41,40,39,38,37,36,35,34,33,32,31,30,29,28,27,26,25,24,23,22,21,20,19,18,17,16,15,14,13,12,11,10,9,8,7,6,5,4,3,2,1,0This works fine in GCC, however, in VC++ 2008 I get the following:warning C4003: not enough actual parameters for macro 'PP_ARG_N'And the result of PP_NARG( ) with whatever arguments ends up expanded to nothing...  To see what arguments PP_ARG_N ends up being called with, I commented out the #define PP_ARG_N ..... and the result is as expected.Here's what I get after the preprocessor if I try PP_ARGN(a, b, c);GCC:3;VC++2008:;In either, if I comment out #define PP_ARG_N ..... :PP_ARG_N(a, b, c, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0);So why the hell is VC++ telling me there aren't enough parameters??!  If I enter the above line directly, it becomes 3; as expected.  So what's going on with VC++?  Is it doing the argument expansion and rescanning in the wrong order?Most importantly, how do I get around this?  How do I change the above set of macros to get the number of items in __VAR_ARG__ in VC++?   
  Looks like it's a confirmed bug by Microsoft in VC++.  It appears related to considering __VA_ARGS__ as a single token instead.The solution I'm using is this:#define LASTARG(_1, _2, _3, _4, _5, _6, _7, _8, _9, N, ...) N#define LEFT_PAREN (#define RIGHT_PAREN )#define ARGCOUNT(...) LASTARG LEFT_PAREN __VA_ARGS__, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0 RIGHT_PARENCompare to standard-compliant preprocessors:#define LASTARG(_1, _2, _3, _4, _5, _6, _7, _8, _9, N, ...) N#define ARGCOUNT(...) LASTARG(__VA_ARGS__, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0)Worse, in order to use ARGCOUNT as an argument in another macro, the workaround has to be used again.  For example, in gcc there's no problem with#define TEST(X, ...) LIST(ARGCOUNT(__VA_ARGS__), X)where LIST is the common macro pattern for expanding into a list, or whatever else.  In VC++2008 this doesn't work and you get an expansion ending up as something like LISTLASTARG.... blah blah.  Instead this would need to be used#define TEST(X, ...) LIST LEFT_PAREN ARGCOUNT(__VA_ARGS__), X RIGHT_PARENTerrible!  I wasted so much time looking for the workarounds.  I hope this is fixed in VC++2010.   ;Quote:Compare to standard-compliant preprocessors:Keep in mind that variadic macros are not standard C++ until C++0x. The 2003 ISO standard does not describe their behavior, nor does it include C99 (which brings variadic macros to the C language). Visual Studio's compiler is niether a C99 compiler nor a C++0x compiler (although it will get some of that in VS2010). Thus the support is an extension in VS.In GCC it's either an extension, coming from the C99 support, or coming from the C++0x support, depending on which flavor of GCC you're running.   ;  Sure, but Microsoft has been claiming VC++ supports variadic macros for years.  When I read the word 'supporting' and see the same token, __VA_ARGS__, being used as is in the C99 standard, I naturally expect that the support is standard compliant.  I'll also mention that Microsoft has admitted directly that this is a bug in VC++ years ago (and remains at least through VC++2008 SP1).   ;Quote:Sure, but Microsoft has been claiming VC++ supports variadic macros for years.Because from their perspective, they have. They've never (to my knowledge) claimed this to be a standard-compliant feature, because they don't claim to be a C99 compiler and there is no C++ standard for them to be compliant to w.r.t to variadic macros. Similarly, just because it's a bug doesn't mean the bug is "does not conform to the standard," because again, there is no standard.   