2011-02-07 22 views
5

E 'possibile fare qualcosa del genere:macro dipendente macro

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

in modo che quando uso F, che si espande per dipende dal fatto che la macro DOUBLE è definito? Io non la penso così, ma sono fiducioso. Le espansioni GNU vanno bene.

Modifica In risposta ad alcune delle risposte, sto molto usare questo per fare un po 'la generazione del codice, dove il codice è leggermente diverso a seconda di dove viene definito. A causa dell'ordine in cui sono inclusi alcuni file e in cui è necessario definire i macro rilevanti, il passaggio da tale posizione richiede un po 'di factoring. Potrei doverlo fare, ma sarei elettrizzato se non dovessi dipanarmi da quest'angolo!

risposta

8

Se siamo in grado di limitare il problema, è possibile ottenere questo risultato. In particolare, se si può garantire che DOUBLE è o

  • non definita come una macro o
  • è definito come una macro che si espande ad una sequenza di token vuoto (per es #define DOUBLE),

poi è possibile utilizzare un approccio indiretto con la concatenazione token: esempio

#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) 

Risultato dopo preelaborazione:

DOUBLE_NOT_DEFINED 
DOUBLE_IS_DEFINED 

Questo approccio funziona anche se DOUBLE (se definito) è definito come una macro che si espande in un unico token noto, se tale token può rientrare un identificatore (ad esempio, TRUE o 1). Per gestire ciò, è sufficiente rinominare la macro F_IMPL_ su F_IMPL_{TOKEN} (ad esempio, F_IMPL_TRUE o F_IMPL_1).

+0

Questo è perfetto. –

+0

Bel lavoro. Mi dispiacerebbe comunque mantenerlo. – AShelly

13

Cosa c'è di sbagliato con

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

perché non fare l'nidificazione il contrario?

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

No. La cosa più vicina che si può fare è quello di mettere che in un file di intestazione, e # include il file di intestazione ogni volta che le definizioni che si preoccupano di cambiare. Questo è talvolta chiamato pattern "X", perché X viene utilizzato come macro che cambia definizione.

Per esempio, un uso comune di questo modello è per autogenerare i nomi di stringa di valori enum:

// 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