C переменный макрос с двумя именованными параметрами - PullRequest
0 голосов
/ 30 декабря 2018

Я хочу использовать макрос с переменным значением, но, похоже, он предназначен только для обработки первого параметра.Я хочу, чтобы первые два параметра были названы, а остальные нет, например:

#define FOO(AA,BB,...) AA->BB(AA,##...)

FOO(mystruct,funcname,123)

Однако это не работает с LLVM.Я делаю что-то не так, или есть ограничение на то, как работает макрос с переменным числом аргументов?


ОБНОВЛЕНИЕ

Правильный ответ: используйте ## VA_ARGS из ## ...

Некоторые веб-страницы утверждают, что «...» допустимо, но по крайней мере в MacOS llvm это не так.

Ответы [ 2 ]

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

... аргументы макроса вставляются в тела макроса с помощью __VA_ARGS__.Проблема в том, как сделать так, чтобы он был пустым.Если оно пустое, вы, как правило, захотите запятую до того, как оно будет стерто, и вы можете использовать расширение GNU ##__VA_ARGS__ для достижения этого.

#define FOO(AA,BB,...) AA->BB(AA,##__VA_ARGS__) /*GNU extension*/
FOO(mystruct,funcname) //warning with -pedantic
FOO(mystruct,funcname,123)

Приведенное выше, однако, вызовет предупреждения, если скомпилировано с -pedantic.Если вы хотите, чтобы ваш макрос использовался без предупреждений на -pedantic, вы могли бы достичь этого, поменяв местами первые два аргумента в определении макроса.

#define FIRST(...)  FIRST_(__VA_ARGS__,)
#define FIRST_(X,...) X
#define BAR_(CallExpr,...) CallExpr(__VA_ARGS__)
#define BAR(BB,/*AA,*/...) BAR_(FIRST(__VA_ARGS__)->BB,__VA_ARGS__)

BAR(funcname,mystruct) //no warning
BAR(funcname,mystruct,123)
0 голосов
/ 30 декабря 2018

Аргументы макроса не раскрываются с помощью ... в расширении макроса - как они могли, потому что тогда у вас не могло быть макроса, который использовал бы многоточие в расширении.Вместо этого он будет доступен как специальный параметр __VA_ARGS__.

. При этом следующая программа

#define FOO(AA,BB,...) AA->BB(AA, __VA_ARGS__)

FOO(mystruct,funcname,123)
FOO(mystruct,funcname,123,456)

будет предварительно обработана до


## является оператором вставки токена.Он сделает один токен предварительной обработки из 2 частей., ## ... пытается создать токен предварительной обработки ,....Это не действительный токен C, и поэтому Clang сообщит

<source>:3:1: error: pasting formed ',...', an invalid preprocessing token 
...