Подсчет количества переменных аргументов в макрофункции - PullRequest
0 голосов
/ 19 декабря 2018

Вот две строки, которые я видел в 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)

Полагаю, это подсчет числа переменных, передаваемых в CV_VA_NUM_ARGS.Для примера возьмем следующий код:

CV_VA_NUM_ARGS(a,b,c)

будет расширен до

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

На данный момент я застрял в понимании происходящего.Конкретно, Я не знаю полезности _1, _2 и т. Д. Кто-нибудь может мне помочь?Вот похожая запись , хотя и более сложная для меня.

РЕДАКТИРОВАТЬ: Когда я не передаю аргументы (скажем CV_VA_NUM_ARGS_HELPER()), макрос будет заменен на 1вместо 0, почему это?

Ответы [ 2 ]

0 голосов
/ 19 декабря 2018

Нет ничего особенного в _1, _2 и т. Д. На их месте могут быть i, j, k.

Значение N зависит от количествааргументы, которые вы передали, потому что N становится 11-м элементом в расширении макроса (из-за 10 заполнителей).

То есть для CV_VA_NUM_ARGS(a,b,c) 11-й элемент равен 3. Для CV_VA_NUM_ARGS(a,b,c,d,e,f) 11-й элемент равен 6 и т. Д.

Обратите внимание, что с этим конкретным кодом вы можете рассчитывать только до10 аргументов.Использование более 10 аргументов приведет к ошибке компилятора.

0 голосов
/ 19 декабря 2018

_1 до _10 являются просто заполнителями с самого начала, чтобы убедиться, что N расположен над правильным числом от 10 до 0 (в зависимости от __VA_ARGS__).Они не служат никакой другой цели, кроме как занимают позицию.

Поскольку каждый параметр макроса должен иметь отдельный идентификатор, эти идентификаторы так же хороши, как и любой.


Что касается вашего редактирования, то это ограничениепрепроцессора.Пустая последовательность токенов является допустимым аргументом макроса.Так что это действительно один аргумент, потому что __VA_ARGS__ , (обратите внимание на запятую) становится таким аргументом.

Это довольно известная проблема, настолько, что C ++ 20 добавил __VA_OPT__ макрос препроцессора.Это позволяет условно добавлять запятую.На C ++ 20 реализация может быть исправлена, чтобы работать как ожидалось, как это:

#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)
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...