Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Count number of variadic arguments in macro function

Tags:

c++

c

macros

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?

like image 624
Finley Avatar asked Nov 18 '25 16:11

Finley


1 Answers

_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)
like image 199
StoryTeller - Unslander Monica Avatar answered Nov 20 '25 06:11

StoryTeller - Unslander Monica



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!