Матрицы Variadic с нулевыми аргументами
Я работаю над макросом вызова,
#define CALL(f,...) FN(f)->call((ref(new LinkedList()), __VA_ARGS__))
который при вызове
CALL(print,2,3,4,5);
добавляет 2 3 4 5 в связанный список (, перегружен для этого) и вызывает печать, которая ожидает связанный список, который работает как ожидалось, как бы там ни было каких-либо вызовов, которые не требуют аргументов,
CALL(HeapSize);
Он по-прежнему занимает связанный список, но пустой, выше не работает, я пытаюсь найти макрос, который работает с любым стилем?
EDIT: выкапывать gug docs. Я обнаружил, что добавление ## до VA_ARGS удаляет, когда нет аргументов, но с этим я не могу вложить макросы,
CALL(print,CALL(HeadSize));
это вызывает CALL не определенную ошибку, как бы то ни было, если я отделяю вызовы, которые он работает
Ответы
Ответ 1
Что касается обновленного вопроса, используя вспомогательный макрос VA_ARGS
like
следующее, аргументы будут расширены, как ожидалось.
#define VA_ARGS(...) , ##__VA_ARGS__
#define CALL(f,...) FN(f)->call((ref(new LinkedList()) VA_ARGS(__VA_ARGS__)))
Ответ 2
Если вы используете GCC, у него есть расширение для проглатывания запятой, предшествующей __VA_ARGS__
. См.: http://gcc.gnu.org/onlinedocs/cpp/Variadic-Macros.html.
Ответ 3
Если вы используете gcc/g++, есть способ:
#define CALL(f,...) FN(f)->call((ref(new LinkedList()), ## __VA_ARGS__))
Из точное руководство:
[...], если аргументы переменной опущены или пусты, оператор `## 'заставляет препроцессор удалять запятую перед ним.
Так что gcc имеет расширение/хак специально для проблемы, с которой вы сталкиваетесь.
Ответ 4
Общей темой в этих ответах является то, что нам нужен конкретный взлом GCC. Один из способов - использовать token-paste ##__VAR_ARGS__
, но вставляемые аргументы не расширены макросами, а это значит, что макросы не могут быть вложенными. Но если вы собираетесь делать что-то конкретное GCC, то почему бы не использовать старомодное расширение GCC:
#define VARARG_FOO(ZeroOrMoreArgs...) \
printf("VARARG_FOO: " ZeroOrMoreArgs)
ZeroOrMoreArgs
просто заменяется всеми аргументами (если они есть), запятыми и всеми. Это включает в себя рекурсивное расширение макросов.
- затем
VARARG_FOO()
расширяется до printf("VARARG_FOO: ")
- и
VARARG_FOO("I iz %d", 42)
расширяется до printf("VARARGFOO: " "I iz %d", 42)
Наконец
#define NEST_ME "I tawt I taw a puddy tat"
VARARG_FOO("The evil one says %s", NEST_ME);
будет расширяться до
printf("VARARG_FOO: " "The evil one says %s", "I tawt I taw a puddy tat");
Плюсы:
- Вы можете вложить макросы-вызовы, имея нулевые или более агитации.
Минусы:
- Хранение
##__VA_ARGS__
может быть безвредным для стандартных программ C в случае, когда у них всегда есть хотя бы одна запятая. (Я не думал о том, верно это или нет).
- В соответствии с @ScootMoonen взлом
##__VA_ARGS__
является недокументированным расширением для MSVC.
Ответ 5
К сожалению, это невозможно. Для этого вызова вам нужно будет определить отдельный макрос.
По мере того, как вы заканчиваете с недействительными аргументами, когда VA_ARGS заменяется ничем, вы получаете плавающий ,
#define CALL0(f) FN(f)->call((ref(new LinkedList())))
Ответ 6
Просто сделайте f
часть ...
и используйте отдельный макрос, чтобы извлечь первый аргумент, где вам нужно f
.