Вариативная макросы без аргументов

Я работаю над макросом вызова,

#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.