Матрицы 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__)))

Ответ 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.