У меня есть два макроса FOO2
и FOO3
:
#define FOO2(x,y) ...
#define FOO3(x,y,z) ...
Я хочу определить новый макрос FOO
следующим образом:
#define FOO(x,y) FOO2(x,y)
#define FOO(x,y,z) FOO3(x,y,z)
Но это не работает, потому что макросы не перегружают количество аргументов.
Без изменения FOO2
и FOO3
, есть какой - то способ определить макрос FOO
( с использованием __VA_ARGS__
или иным образом ) , чтобы получить тот же эффект , диспетчерские FOO(x,y)
к FOO2
, и FOO(x,y,z)
к FOO3
?
c
macros
c-preprocessor
Андрей Томазос
источник
источник
Ответы:
Просто как:
Итак, если у вас есть эти макросы:
Если вы хотите четвертый:
Естественно, если вы определите
FOO2
,FOO3
иFOO4
, выходные данные будут заменены теми из определенных макросов.источник
EXPAND
упомянутое в ссылке @ Étienne, вы в основном вызываете егоGET_MACRO
примерно так,#define FOO(...) EXPAND(GET_MACRO(__VA_ARGS__, FOO3, FOO2, FOO1)(__VA_ARGS__))
и он должен расшириться до нужного числа аргументов в msvc.ISO C++11 requires at least one argument for the "..." in a variadic macro
. Чтобы это исправить, добавьте неиспользуемый аргумент (или даже просто запятую) после последнего параметра в определении FOO (...):#define FOO(...) GET_MACRO(__VA_ARGS__, FOO3, FOO2, UNUSED)(__VA_ARGS__)
( смотрите, как он работает на Coliru ).Чтобы добавить ответ netcoder , вы МОЖЕТЕ сделать это с помощью макроса с 0 аргументами с помощью
##__VA_ARGS__
расширения GCC :источник
#define FOO0 _Pragma("error FOO0 not allowed")
?FOO0
не работает в qt + mingw32, вызовFOO0
вызоветFOO1
-std=c99
или-std=c11
. Вы должны использовать-std=gnu99
или-std=gnu11
вместо этого_0, ##__VA_ARGS__
на_0 __VA_OPT__(,) __VA_ARGS__
это новый способ сделать это.Вот более общее решение:
Определите свои функции:
Теперь вы можете использовать
FOO
с 2, 3 и 4 аргументами:Ограничения
идеи
Используйте его для аргументов по умолчанию:
Используйте его для функций с возможным бесконечным числом аргументов:
PS:
__NARG__
скопировано с Laurent Deniau & Roland Illig здесь: https://groups.google.com/group/comp.std.c/browse_thread/thread/77ee8c8f92e4a3fb/346fc464319b1ee5?pli=1источник
__NARG_I_
кажется совершенно ненужным и лишним. Это просто добавляет дополнительный шаг и путаницу. Я рекомендую удалить его полностью и просто определение ,__NARG__
а не как:#define __NARG__(...) __ARG_N(__VA_ARGS__,__RSEQ_N())
._VFUNC_
: просто удалите это. Затем определите_VFUNC
как:#define _VFUNC(name, n) name##n
вместо#define _VFUNC(name, n) _VFUNC_(name, n)
.Я только что исследовал это сам, и я столкнулся с этим здесь . Автор добавил поддержку аргументов по умолчанию для функций C через макросы.
Я постараюсь кратко подвести итог статьи. По сути, вам нужно определить макрос, который может считать аргументы. Этот макрос вернет 2, 1, 0 или любой другой диапазон аргументов, которые он может поддерживать. Например:
При этом вам нужно создать другой макрос, который принимает переменное число аргументов, считает аргументы и вызывает соответствующий макрос. Я взял твой пример макроса и соединил его с примером статьи. У меня есть функция вызова FOO1 a () и функция вызова FOO2 a с аргументом b (очевидно, я предполагаю C ++ здесь, но вы можете изменить макрос на что угодно).
Так что если у вас есть
Препроцессор расширяет это до
Я определенно прочитал бы статью, которую я связал. Это очень информативно, и он упоминает, что NARG2 не будет работать на пустых аргументах. Он следует за этим здесь .
источник
Вот более компактная версия ответа выше . С примером.
Бегать:
Обратите внимание , что наличие как
_OVR
и_OVR_EXPAND
может выглядеть излишним, но это необходимо для препроцессора расширить_COUNT_ARGS(__VA_ARGS__)
часть, которая в противном случае трактуется как строка.источник
Может быть, вы можете использовать этот макрос для подсчета количества аргументов .
источник
Вот ответ от Евгения Сергеева. Этот поддерживает нулевые перегрузки аргументов !
Я проверил это с GCC и MinGW. Он должен работать со старыми и новыми версиями C ++. Обратите внимание, что я не гарантирую это для MSVC ... Но с некоторыми изменениями, я уверен, что это может быть сделано для работы с этим тоже.
Я также отформатировал это, чтобы вставить в файл заголовка (который я назвал macroutil.h). Если вы сделаете это, вы можете просто включить этот заголовок в любую нужную вам функцию, а не смотреть на злобу, связанную с реализацией.
источник
Похоже, это хорошо работает на GCC, Clang и MSVC. Это исправленная версия некоторых ответов здесь
источник
#define func0() foo
? Текущая версия, к сожалению, не обрабатывает этот случай.