Here is a macro can calculate the count of arguments. and the code like:
#define Y_TUPLE_SIZE_II(__args) Y_TUPLE_SIZE_I __args
#define Y_TUPLE_SIZE_PREFIX__Y_TUPLE_SIZE_POSTFIX ,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,0
#define Y_TUPLE_SIZE_I(__p0,__p1,__p2,__p3,__p4,__p5,__p6,__p7,__p8,__p9,__p10,__p11,__p12,__p13,__p14,__p15,__p16,__p17,__p18,__p19,__p20,__p21,__p22,__p23,__p24,__p25,__p26,__p27,__p28,__p29,__p30,__p31,__n,...) __n
#define MPL_ARGS_SIZE(...) Y_TUPLE_SIZE_II((Y_TUPLE_SIZE_PREFIX_ ## __VA_ARGS__ ## _Y_TUPLE_SIZE_POSTFIX,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))
// the running result ---------------------------------------
MPL_ARGS_SIZE(a,b,c,d,e,f,g)==7
MPL_ARGS_SIZE(a,b,c,d)==4
how to understand
#define Y_TUPLE_SIZE_PREFIX__Y_TUPLE_SIZE_POSTFIX ,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,0
and
Y_TUPLE_SIZE_PREFIX_ ## __VA_ARGS__ ## _Y_TUPLE_SIZE_POSTFIX
?
BTW, I know about ##(pound, pound) usage and the mechanism of #define Y_TUPLE_SIZE_I
The PREFIX and POSTFIX macros are intended to make it give 0 when no arguments are given, i.e. MPL_ARGS_SIZE()
. In this case, Y_TUPLE_SIZE_PREFIX_
and _Y_TUPLE_SIZE_POSTFIX
are concatenated to produce Y_TUPLE_SIZE_PREFIX__Y_TUPLE_SIZE_POSTFIX
, which forces the result to 0.
In the general case, __VA_ARGS__
is non-empty, so the concatenation just expands to the same number of arguments that were given. This is followed by 32, ... 0.
In both cases, the arguments are wrapped in parentheses. Y_TUPLE_SIZE_II
strips off these extra parentheses and passes the arguments on to Y_TUPLE_SIZE_I
. Y_TUPLE_SIZE_I
just expands to its 33rd argument, discarding the rest.
So if you give it 32 arguments, those 32 will be skipped and the number following them, 32, will be the result, as desired. If you give it 31 arguments, it will skip those 31, and the first number that follows, i.e. 32, and the result will be the next number, 31, again as desired.
If you give it a single argument, it will skip that argument and the 31 that follow it, and the result will be 1.
If you give it no arguments, the special case of Y_TUPLE_SIZE_PREFIX__Y_TUPLE_SIZE_POSTFIX
will come into play, which is 32 empty arguments followed by 0. The 32 empty arguments will be skipped, and the result will be 0.
The reason for the special case for no arguments is that without it, it would behave the same as the one-argument case. The following might help understand it better:
#define Y_TUPLE_SIZE_II(__args) Y_TUPLE_SIZE_I __args
#define Y_TUPLE_SIZE_I(__p0,__p1,__p2,__p3,__p4,__p5,__p6,__p7,__p8,__p9,__p10,__p11,__p12,__p13,__p14,__p15,__p16,__p17,__p18,__p19,__p20,__p21,__p22,__p23,__p24,__p25,__p26,__p27,__p28,__p29,__p30,__p31,__n,...) __n
#define MPL_ARGS_SIZE(...) Y_TUPLE_SIZE_II((__VA_ARGS__,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))
This is the original set of macros, but with all of the special-case handling for zero arguments removed. It works for everything but the zero-argument case, which returns 1 instead of 0.
In order to handle zero arguments, it sandwiches the argumement list between the prefix and postfix macros. If the result expands to Y_TUPLE_SIZE_PREFIX__Y_TUPLE_SIZE_POSTFIX
, then the argument list was empty, and the special case comes into play.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With