## __VA_NARG__

Showing 1-10 of 10 messages
 __VA_NARG__ Laurent Deniau 1/16/06 9:43 AM Hi all,A year ago, I was asking here for an equivalent of __VA_NARG__ which would return the number of arguments contained in __VA_ARGS__ before its expansion. In fact my problem at that time (detecting for a third argument) was solved by the solution of P. Mensonides. But I was still thinking that the standard should have provided such a facilities rather easy to compute for cpp.This morning I had to face again the same problem, that is knowing the number of arguments contained in __VA_ARGS__ before its expansion (after its expansion can always be achieved if you can do it before). I found a simple non-iterative solution which may be of interest here as an answer to who will ask in the future for a kind of __VA_NARG__ in the standard and I post it for archiving. May be some more elegant-efficient solution exists?regards,ld.Returns NARG, the number of arguments contained in __VA_ARGS__ before expansion as far as NARG is >0 and <64 (cpp limits):#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,[..],_61,_62,_63,N,...) N#define PP_RSEQ_N() 63,62,61,60,[..],9,8,7,6,5,4,3,2,1,0[..] stands for the continuation of the sequence omitted here for lisibility.PP_NARG(A) -> 1PP_NARG(A,B) -> 2PP_NARG(A,B,C) -> 3PP_NARG(A,B,C,D) -> 4PP_NARG(A,B,C,D,E) -> 5PP_NARG(A1,A2,[..],A62,A63) -> 63 Re: __VA_NARG__ Roland Illig 1/20/06 3:58 AM Laurent Deniau wrote:> This morning I had to face again the same problem, that is knowing the > number of arguments contained in __VA_ARGS__ before its expansion (after > its expansion can always be achieved if you can do it before). I found a > simple non-iterative solution which may be of interest here as an answer > to who will ask in the future for a kind of __VA_NARG__ in the standard > and I post it for archiving. May be some more elegant-efficient solution > exists?Thanks for this idea. I really like it.For those that only want to copy and paste it, here is the expanded version:/* The PP_NARG macro returns the number of arguments that have been  * passed to it.  */#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,0/* Some test cases */PP_NARG(A) -> 1PP_NARG(A,B) -> 2PP_NARG(A,B,C) -> 3PP_NARG(A,B,C,D) -> 4PP_NARG(A,B,C,D,E) -> 5PP_NARG(1,2,3,4,5,6,7,8,9,0,         1,2,3,4,5,6,7,8,9,0,         1,2,3,4,5,6,7,8,9,0,         1,2,3,4,5,6,7,8,9,0,         1,2,3,4,5,6,7,8,9,0,         1,2,3,4,5,6,7,8,9,0,         1,2,3) -> 63Note: using PP_NARG() without arguments would violate 6.10.3p4 of ISO C99. Re: __VA_NARG__ Laurent Deniau 1/20/06 4:16 AM Right. I try to ensure that I always have at least one argument in my macros which are expected to accept arguments (like for variadic functions).Thanks for the pretty expanded version.ld. Re: __VA_NARG__ arpad.g...@gmail.com 4/22/12 4:31 AM I extended this to also work correctly with 0 arguments (but now it will accept only 62 arguments): #define __VA_NARG__(...) \         (__VA_NARG_(_0, ## __VA_ARGS__, __RSEQ_N()) - 1) #define __VA_NARG_(...) \         __VA_ARG_N(__VA_ARGS__) #define __VA_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 __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,  0 Hope this helps. Re: __VA_NARG__ Jens Gustedt 4/22/12 9:10 AM Hello, it seems that you are using the ``, ##'' extension of gcc to achieve your goal. This is not standard, and so in particular this news group is probably not appropriate. There are other, more standard ways around this problem of detecting if a va_arg macro is called with an empty argument. Unfortunately none of them is completely error prone, but at least some are usably in practise. In that sense it would be really nice, I agree, if there would be a standard functionality to achieve that goal. For the moment the preprocessing phase doesn't foresee much of "meta" functions. So this would be a substatial change of the pattern, not likely to happen. Jens Re: __VA_NARG__ zhangj...@gmail.com 1/29/15 8:05 PM (__VA_NARG_(_0, ## __VA_ARGS__, __RSEQ_N())) #define __VA_NARG_(...) \         __VA_ARG_N(__VA_ARGS__) #define __VA_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 __RSEQ_N() \         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,  0 we needn't add "-1" after __RSEQ_N(), only remove "63," in __RSEQ_N. that's OK Re: __VA_NARG__ mad...@acm.org 1/30/15 7:41 AM On Sunday, April 22, 2012 at 12:10:53 PM UTC-4, Jens Gustedt wrote: > Hello, > it seems that you are using the ``, ##'' extension of gcc to achieve > your goal. This is not standard, and so in particular this news group > is probably not appropriate. > Jens Actually the ## pasting operator is completely standard.  See ISO/IEC 9899:1999(E) 6.10.3.3. Randy. Re: __VA_NARG__ Kaz Kylheku 1/30/15 11:23 AM I don't see any claim that ## is not standard. Re: __VA_NARG__ seshr...@gmail.com 1/31/15 3:43 PM https://gcc.gnu.org/onlinedocs/cpp/Variadic-Macros.html According to this page the '##' operator has a special meaning in this context using GCC CPP. Re: __VA_NARG__ Keith Thompson 1/31/15 3:54 PM The post by Jens refers to ## following a comma, which is a gcc (actually GNU cpp) extension.  It's easy to miss the comma between the `` and '' delimiters and assume he was saying that ## itself is an extension. In any case, the article was posted in 2012; it's likely this was already covered at the time (I'm too lazy to go back and check). -- Keith Thompson (The_Other_Keith) ks...@mib.org   Working, but not speaking, for JetHead Development, Inc. "We must do something.  This is something.  Therefore, we must do this."     -- Antony Jay and Jonathan Lynn, "Yes Minister"