2012-04-19 11 views
6

me gustaría hacer algo como esto:¿Es posible que una macro evalúe múltiples argumentos a otro?

#define NEED3ARGS(a1,a2,a3) ("[" #a1 " + " #a2 " + " #a3 "]") 
#define MULTIARG() ARG1, ARG2, ARG3 

NEED3ARGS(MULTIARG()) 

Y yo esperaba que seria algo así como:

("[" "ARG1" " + " "ARG2" " + " "ARG3" "]") 

Pero en vez tengo:

$ cpp multiarg.c 
# 1 "multiarg.c" 
# 1 "<built-in>" 
# 1 "<command-line>" 
# 1 "multiarg.c" 

multiarg.c:4:23: error: macro "NEED3ARGS" requires 3 arguments, but only 1 given 
NEED3ARGS 

¿Existe una forma de hacer lo que quiero usando ANSI-C/GNU GCC y el preprocesador C?

Gracias!

Respuesta

12

Necesita un poco de direccionamiento indirecto. Con C99:

#define NEED3ARGS(a1,a2,a3) ("[" #a1 " + " #a2 " + " #a3 "]") 
#define INVOKE_NEED3ARGS(...) NEED3ARGS(__VA_ARGS__) 
#define MULTIARG() ARG1, ARG2, ARG3 

INVOKE_NEED3ARGS(MULTIARG()) 

(. C99 no es estrictamente necesario, se puede sustituir la macro variadic con una macro-aridad fijo)

Si necesita compilar las fuentes utilizando Visual C++, se le necesitará aún más indirecta (a causa de a compiler bug):

#define NEED3ARGS(a1,a2,a3) ("[" #a1 " + " #a2 " + " #a3 "]") 
#define INVOKE_NEED3ARGS_(...) NEED3ARGS __VA_ARGS__ 
#define INVOKE_NEED3ARGS(...) INVOKE_NEED3ARGS_((__VA_ARGS__)) 
#define MULTIARG() ARG1, ARG2, ARG3 

INVOKE_NEED3ARGS(MULTIARG()) 

en cuanto a por qué se necesita indirecto: un argumento macro no es Evalu ated y macro-reemplazado hasta que se sustituya en la lista de reemplazo. Por lo tanto, cuando intente NEED3ARGS(MULTIARG()), MULTIARG() no se evaluará hasta que después de haya comenzado la invocación de macro, por lo que se trata como un único argumento.

La macro INVOKE_NEED3ARGS asegura que sus argumentos se evalúen completamente antes de invocar NEED3ARGS. El __VA_ARGS__ se sustituye por los argumentos macro-reemplazados en INVOKE_NEED3ARGS, que es ARG1, ARG2, ARG3, luego se invoca NEED3ARGS con esos argumentos.

6

Sí,

#define NEED3ARGS(a1,a2,a3) ("[" #a1 " + " #a2 " + " #a3 "]") 
#define MULTIARG() ARG1, ARG2, ARG3 
#define NEED1ARG(ARG) NEED3ARGS(ARG) 

NEED1ARG(MULTIARG()) 

Necesitas envolverlo en otra llamada macro por lo que el argumento se expanden antes NEED3ARGS se llama.

1

Añadiendo a la respuesta de James McNellis, si necesita aplicar este truco a muchas macros funcionales (flm), podría definir una sola macro "invocar" para hacer el truco por usted. Aquí hay un ejemplo completo de trabajo:

#include<cstdio> 
int f(int x,int y) { return x + y; } 
#define g(x,y) x+y 
#define XY 1,2 
#define _g(arg) g(arg) 
#define invoke(flm,...) flm(__VA_ARGS__) 
int main(int argc, char ** argv) 
{ 
    printf("%d\n",f(XY));  // functions are easy 
    printf("%d\n",_g(XY));  // Jam,es' way 
    printf("%d\n",invoke(g,XY)); // with generic invoke flm 
    return 0; 
} 
Cuestiones relacionadas