简体   繁体   中英

Count number of variadic arguments in macro function

Here are two lines I saw in OpenCV

#define CV_VA_NUM_ARGS_HELPER(_1, _2, _3, _4, _5, _6, _7, _8, _9, _10, N, ...)    N
#define CV_VA_NUM_ARGS(...)      CV_VA_NUM_ARGS_HELPER(__VA_ARGS__, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0)

I guess it is to count the number of variadic arguments passing to CV_VA_NUM_ARGS . Take following code for example:

CV_VA_NUM_ARGS(a,b,c)

will be extended to

CV_VA_NUM_ARGS_HELPER(a,b,c,10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0)

At this point, I am stuck on understanding what is going on. Concretely, I don't know the utility of _1 , _2 ,etc. Can anyone help me out? Here is a similar post while more complex to me.

EDIT: When I pass no arguments(say CV_VA_NUM_ARGS_HELPER() ), the macro will be replaced by 1 instead of 0, why is that?

_1 to _10 are just placeholders from the start in order to make sure N is positioned over the correct number from 10 to 0 (depending on __VA_ARGS__ ). They serve no purpose other than occupying a position.

Since each macro parameter must have a distinct identifier, those identifiers are as good as any.


Regarding your edit, that is limitation of the preprocessor. An empty token sequence is a valid argument to a macro. So it really is a single argument, because __VA_ARGS__ , (note the comma) becomes such an argument.

It's quite a known issue, so much so that C++20 added the __VA_OPT__ preprocessor macro. It allows to add the comma conditionally. On C++20, the implementation can be fixed to work as expected like this:

#define CV_VA_NUM_ARGS(...)      CV_VA_NUM_ARGS_HELPER(__VA_ARGS__ __VA_OPT__(,) 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0)

There is nothing special about _1 , _2 etc. You can have i , j , k in their place.

The value of N depends on the number of arguments you have passed because N becomes the 11th element in the macro expansion (because of the 10 place holders).

So for CV_VA_NUM_ARGS(a,b,c) , the 11th element is 3. For CV_VA_NUM_ARGS(a,b,c,d,e,f) , the 11th element is 6 and so on.

Note that with this particular code you can count only up to 10 arguments. Using more than 10 arguments will generate a compiler error.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM