macro define __va_args__ c++ gcc c-preprocessor variadic-macros

c++ - define - Macros variables con cero argumentos.



c++ define macro (6)

Estoy trabajando en una macro de llamada,

#define CALL(f,...) FN(f)->call((ref(new LinkedList()), __VA_ARGS__))

que cuando se llama,

CALL(print,2,3,4,5);

agrega 2 3 4 5 a la lista vinculada (, está sobrecargado para hacerlo) y imprime las llamadas que esperan una lista vinculada que funciona como se espera, sin embargo, hay algunas llamadas que no requieren argumentos,

CALL(HeapSize);

Todavía se necesita una lista enlazada, pero una vacía, la anterior no funciona. ¿Estoy tratando de crear una macro que funcione con cualquiera de los dos estilos?

EDITAR: Excavando a través de documentos gcc, encontré que al agregar ## antes de que VA_ARGS elimine, cuando no hay argumentos pero con eso no puedo anidar macros,

CALL(print,CALL(HeadSize));

esto causa un error de CALL no definido, si separo las llamadas que funcionan


Desafortunadamente esto no se puede hacer. Necesitará definir una macro separada para hacer esta llamada.

Cuando terminas con argumentos inválidos cuando VA_ARGS es sustituido por nada, terminas con un flotante ,

#define CALL0(f) FN(f)->call((ref(new LinkedList())))


En cuanto a la pregunta actualizada, mediante el uso de la macro auxiliar VA_ARGS como la siguiente, los argumentos se expandirán como se espera.

#define VA_ARGS(...) , ##__VA_ARGS__ #define CALL(f,...) FN(f)->call((ref(new LinkedList()) VA_ARGS(__VA_ARGS__)))



Si estás usando gcc / g ++ hay una manera:

#define CALL(f,...) FN(f)->call((ref(new LinkedList()), ## __VA_ARGS__))

De la multa manual :

[...] si los argumentos variables se omiten o están vacíos, el operador `## ''hace que el preprocesador elimine la coma anterior.

Así que gcc tiene una extensión / hack específicamente para el problema al que te enfrentas.


Simplemente haga f parte del ... y use una macro separada para extraer el primer argumento donde necesita f .


Un tema común en estas respuestas es que necesitamos un truco específico de GCC. Una forma es usar el token-paste ##__VAR_ARGS__ , pero los argumentos pegados no se expanden en macro, lo que significa que las macros no se pueden anidar. Pero si vas a hacer algo específico de GCC de todos modos, entonces, ¿por qué no usar la antigua extensión GCC:

#define VARARG_FOO(ZeroOrMoreArgs...) / printf("VARARG_FOO: " ZeroOrMoreArgs)

ZeroOrMoreArgs simplemente es reemplazado por todos los argumentos (si los hay), comas y todos. Esto incluye la expansión macro recursiva.

  • entonces VARARG_FOO() expande a printf("VARARG_FOO: ")
  • y VARARG_FOO("I iz %d", 42) expande a printf("VARARGFOO: " "I iz %d", 42)

Finalmente

#define NEST_ME "I tawt I taw a puddy tat" VARARG_FOO("The evil one says %s", NEST_ME);

se expandirá a

printf("VARARG_FOO: " "The evil one says %s", "I tawt I taw a puddy tat");

Pros:

  • Puede anidar invocaciones de macro, mientras tenga cero o más documentos.

Contras:

  • El ##__VA_ARGS__ hack puede ser inofensivo en los programas estándar de C en el caso de que siempre tengan al menos una coma. (No he pensado si esto es cierto o no).
  • Según @ScootMoonen, el ##__VA_ARGS__ hack es una extensión no documentada de MSVC.