2011-05-05 17 views
13

estoy trabajando en una macro llamada,macros variadic con cero argumentos

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

que cuando se llama,

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

añade 2 3 4 5 de la lista enlazada (, está sobrecargado para hacerlo) y las llamadas se imprimen, lo que espera una lista vinculada que funcione como se espera, aunque haya algunas llamadas que no requieren argumentos,

CALL(HeapSize); 

Todavía toma una lista vinculada pero una vacía, arriba no funciona, ¿estoy tratando de encontrar una macro que funcione con cualquiera de los dos estilos?

EDIT: Digging throug docs gcc he encontrado que la adición de ## antes de VA_ARGS elimina el, cuando no hay argumentos, pero con eso no puedo macros nido,

CALL(print,CALL(HeadSize)); 

esto hace que la llamada no se define de error Cómo siempre, si separo las llamadas funciona

+1

Puede tener el delegado 'CALL' en diferentes macros dependiendo de la cantidad de argumentos que se pasan. Demostré cómo hacer esto [en una respuesta a otra pregunta] (http://stackoverflow.com/questions/5355241/generating-function-declaration-using-a-macro-iteration/5355946#5355946). Esto no requiere ningún hackeo específico de implementación. –

+0

también vea http://stackoverflow.com/questions/5588855/standard-alternative-to-gccs-va-args-trick –

Respuesta

14

En cuanto a la pregunta actualizada, mediante el uso de la macro auxiliar VA_ARGS como , los argumentos se ampliarán según lo esperado.

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

P.S. Esto funcionó bien en mi caso donde necesitaba agregar NULL al final: #define blah (x, ...) real (a, b, c, ## _VA_ARGS __, NULL) – Brad

+1

Siempre he estado usando este truco hasta que descubrí que en el modo pedante de gcc al compilar para C99 o incluso C11, esto produce una advertencia. Bueno, no es exactamente esta definición de macro en sí misma, sino que llama a una macro variable con una parte variable cero. ¿Por qué, oh por qué no lo permitieron en el estándar C11? –

0

Desafortunadamente esto no se puede hacer. Tendrá que definir una macro por separado para hacer esta llamada.

Como se termina con argumentos no válidos al VA_ARGS se sustituye con nada se termina con una flota ,

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

Si está utilizando GCC, que tiene una extensión de tragar hasta la coma que precede a la __VA_ARGS__. Ver: http://gcc.gnu.org/onlinedocs/cpp/Variadic-Macros.html.

+0

Solo porque la suya es más exhaustiva. :) –

+0

Y MSVC, aunque no se menciona en su página MSDN, admite la misma extensión, facilitando la vida de todos. – vanza

+3

@vanza: en realidad, MSVC lo hace por usted "automáticamente" - si tiene la secuencia ', __VA_ARGS__' en una macro y' __VA_ARGS__' está vacía, automáticamente tragará (eliminará) ','. También ignora '##' si está entre dos tokens que no se pueden combinar, por lo que la extensión gcc funciona por casualidad. –

3

Si está utilizando gcc/g ++ hay una manera:

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

Desde el fine manual:

[...] si los argumentos variables se omiten o se vacía, el ` ## 'hace que el preprocesador elimine la coma que tiene delante.

Así gcc tiene una extensión/pirateo específicamente para el problema al que se enfrenta.

+1

He editado la pregunta, he encontrado lo mismo en los documentos, pero con ella no puedo anidar macros –

0

Simplemente haga f parte de ..., y use una macro separada para extraer el primer argumento donde necesite f.

1

Un tema común en estas respuestas es que necesitamos un hack específico de GCC. Una forma es usar 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 usted va a hacer algo GCC específica de todos modos, ¿por qué no usar la antigua extensión de GCC:

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

ZeroOrMoreArgs simplemente se sustituye por todos los argumentos (si los hay), comas y todo. Esto incluye la expansión de 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 macro invocaciones, mientras que tienen cero o más aguments.

Contras:

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