2010-11-04 20 views
18

Ho una serie di macro di debug in tracing.hh. Sia che si genera il codice e l'uscita è controllata da una bandiera macro nel codice sorgente reale:Test per definizione macro vuota

// File: foo.cc 
#define TRACING 0 
#include "tracing.hh" 
// Away we go . . . 
TRACEF("debug message"); 

rintracciamento bandiera dovrebbe avere un valore; Io di solito alternare tra 0 e 1.

All'interno tracing.h,

  • #ifdef TRACING mi dirà che il tracciamento è stato definito.
  • #if TRACING controlli la definizione di macro funzionali come TRACEF()

Ma cosa succede se questa funzionalità non ha alcun valore? Poi #if TRACING produce un errore:

In file included from foo.c:3: 
tracing.hh:73:12: error: #if with no expression 

Come posso verificare se questa funzionalità è definito, ma non ha alcun valore?

risposta

0

Sarebbe

#if defined(TRACING) && !TRACING 

fare il trucco?

+0

Quasi, penso. Guarda la prossima risposta: – pdbj

+4

Questo purtroppo non funzionerà. Incontrerai lo stesso problema, dove verrà rimosso TRACING. Finirai con qualcosa del tipo: "#if definito (TRACING) &&!". Quindi, "errore: operatore '!' non ha un operando corretto "aumenterà al momento della compilazione. – ForceMagic

22

Con il suggerimento di Matti e qualche altro spunto, penso che il problema sia questo: se TRACING non ha valore, abbiamo bisogno di un'espressione di preprocessore valida nel test #if .... Lo dice che deve valutare un'espressione intera, quindi abbiamo bisogno di un'espressione valida anche se manca uno degli argomenti. Quello che mi ha colpito finalmente on è:

#if (TRACING + 0) 
# . . . 
  • Se TRACING ha un valore numerico (come in #define TRACING 2 \n), cpp ha un'espressione valida, e non abbiamo cambiato il valore
  • Se TRACING non ha valore. (come in #define TRACING \n), il preprocessore restituisce #if (+0) a false

l'unico caso questo non gestisce è

  • Se TRACING ha un valore token (, ad esempio, ON). Il manuale cpp dice "Gli identificatori che non sono macro ... sono tutti considerati come il numero zero,", che valuta false. In questo caso, tuttavia, avrebbe più senso considerarlo come un valore true. Gli unici token che fanno la cosa giusta sono i letterali booleani true e false.
+0

È ancora possibile eseguire un test in fase di esecuzione impostando la macro su una stringa utilizzando l'operatore '#'. C++ 11 potrebbe essere in grado di trasformarlo in un test in fase di compilazione (suppongo che l'uso di 'constexpr' potrebbe essere un modo) ma non quello di un preprocessore. –

+0

anche tu non hai modo di distinguere tra vuoto e 'TRACING' uguale a 0 –

+0

' # if' definisce a 0 se non trovato. quello non funziona –

1

in ritardo alla festa, ma ho trovato un bel trucco per distinguere -DTRACING=0 da -DTRACING:

#if (0-TRACING-1)==1 && (TRACING+0)!=-2 
#error "tracing empty" 
#endif 

Se TRACING è vuota, l'espressione restituisce 0--1 =>1.

Se TRACING è 0, l'espressione restituisce 0-0-1 =>-1

ho aggiunto un controllo extra in caso TRACING==-2 che renderebbe il primo passaggio di prova.

Questo non funziona per i letterali di stringa, ovviamente.

Problemi correlati