Вариативная макросы без аргументов
Я работаю над макросом вызова,
#define CALL(f,...) FN(f)->call((ref(new LinkedList()), __VA_ARGS__))
при вызове,
CALL(print,2,3,4,5);
добавляет 2 3 4 5 В связанный список (, перегружен для этого) и вызывает печать, которая ожидает связанный список, который работает так, как ожидалось, как когда-либо есть некоторые вызовы, которые не требуют аргументов,
CALL(HeapSize);
Он по-прежнему занимает связанный список, но пустой, выше не работает, я пытаюсь придумать макрос, который не работает либо стиль?
изменить: Копая документы GCC, я обнаружил, что добавление ## до VA_ARGS удаляет , когда нет аргументов, но с этим я не могу Нест макросы,
CALL(print,CALL(HeadSize));
это вызывает вызов не определенной ошибки, как когда-либо, если я отделяю вызовы, которые он работает
6 ответов
что касается обновленного вопроса, то с помощью вспомогательного макроса VA_ARGS
как
Ниже приводятся аргументы, которые будут расширены, как и ожидалось.
#define VA_ARGS(...) , ##__VA_ARGS__
#define CALL(f,...) FN(f)->call((ref(new LinkedList()) VA_ARGS(__VA_ARGS__)))
Если вы используете gcc / g++, есть способ:
#define CALL(f,...) FN(f)->call((ref(new LinkedList()), ## __VA_ARGS__))
[...] если аргументы переменной опущены или пусты, оператор `##' заставляет препроцессор удалить запятую перед ним.
таким образом, gcc имеет расширение / Хак специально для Проблемы, с которой вы столкнулись.
Если вы используете GCC, у него есть расширение, чтобы проглотить запятую, предшествующую __VA_ARGS__
. Смотри:http://gcc.gnu.org/onlinedocs/cpp/Variadic-Macros.html.
общей темой в этих ответах является то, что нам нужен конкретный взлом 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");
плюсы:
- вы можете вложить вызовы макросов, имея ноль-или более aguments.
плюсы:
- на
##__VA_ARGS__
hack может будет защищать стандартные программы C в том случае, когда у них всегда есть хотя бы одна запятая. (Я не думал о том, правда это или нет). - согласно @ScootMoonen
##__VA_ARGS__
hack является недокументированным расширением MSVC.
к сожалению, это невозможно сделать. Для выполнения этого вызова необходимо определить отдельный макрос.
Как вы в конечном итоге с недопустимыми аргументами, когда VA_ARGS заменяется ничего, что вы в конечном итоге с плавающей ,
#define CALL0(f) FN(f)->call((ref(new LinkedList())))
просто f
часть ...
, и использовать отдельный макрос для извлечения первого аргумента, где вам нужно f
.