2011-02-07 26 views
5

¿Es posible hacer algo como esto:macro macro dependiente

se define
#define F(x) \ 
    #ifdef DOUBLE \ 
     2*x \ 
    #else \ 
     x \ 
    #endif 

de manera que cuando uso F, lo que amplía a depende de si la macro DOUBLE? No lo creo, pero tengo esperanzas. Las expansiones de GNU están bien.

Editar En respuesta a algunas de las respuestas, realmente estoy usando esto para hacer un poco de la generación de código, donde el código es ligeramente diferente dependiendo de donde se define. Debido al orden en el que se incluyen algunos archivos y donde deben definirse las macros relevantes, cambiarlo de esa manera requiere un poco de factorización. Puede que tenga que hacerlo, pero estaría encantado si no tuviera que deshacerme de esta esquina.

Respuesta

8

Si podemos limitar el problema, se puede lograr esto. Específicamente, si se puede garantizar que DOUBLE es o bien

  • no definida como una macro, o
  • se define como un macro que se expande a una secuencia de tokens vacío (por ejemplo #define DOUBLE),

entonces puede utilizar un enfoque indirecto con la concatenación de símbolos: ejemplo

#define F_IMPL_(x)  DOUBLE_IS_DEFINED 
#define F_IMPL_DOUBLE(x) DOUBLE_NOT_DEFINED 

#define F_1(x, m) F_2(x, m) 
#define F_2(x, m) F_IMPL_ ## m (x) 

#define F(x) F_1(x, DOUBLE) 

uso:

F(t) 
#define DOUBLE 
F(t) 

Resultado después de preprocesamiento:

DOUBLE_NOT_DEFINED 
DOUBLE_IS_DEFINED 

Este enfoque también funcionará si DOUBLE (si se define) se define como una macro que se expande a un solo contador conocida, si esa señal puede formar parte de un identificador (p. ej., TRUE o 1). Para manejar esto, solo tiene que cambiar el nombre de la macro F_IMPL_ al F_IMPL_{TOKEN} (por ejemplo, F_IMPL_TRUE o F_IMPL_1).

+0

Eso es perfecto. –

+0

Buen trabajo. Aunque odiaría mantenerlo. – AShelly

13

¿Qué hay de malo en

#ifdef DOUBLE 
    #define F(x) (2 * (x)) 
#else 
    #define F(x) (x) 
#endif 
4

¿Por qué no la anidación al revés?

#ifdef DOUBLE 
#define F(x) (2*(x)) 
#else 
#define F(x) (x) 
#endif 
3

No. Lo más cercano que puede hacer es poner esto en un archivo de cabecera, y # include ese archivo de cabecera cada vez que las definiciones que se preocupan por el cambio. Esto a veces se denomina el patrón "X" porque X se usa como una macro que cambia la definición.

Por ejemplo, un uso común de que el patrón es autogenerar los nombres de cadena de valores de enumeración:

// File myenum_values.h 
// NOTE: _no_ header guards so we can include this file multiple times 
X(Apple) 
X(Orange) 
X(banana) 

// File myenum.h 
enum Fruit 
{ 
#define X(x) x, 
#include "myenum_values.h" 
} 

const char *FruitNames[] = 
{ 
#undef X 
#define X(x) #x, 
#include "myenum_values.h" 
}; 

// We now have an array of fruit names without having to define the enum twice