2009-11-24 10 views
35

Sto utilizzando sia la libreria JUCE che un numero di intestazioni Boost nel mio codice. Juce definisce "T" come una macro (gemito), e Boost spesso usa "T" nelle sue definizioni di template. Il risultato è che se in qualche modo includi le intestazioni JUCE prima delle intestazioni Boost, il preprocessore espande la macro JUCE nel codice Boost, e quindi il compilatore viene perso irrimediabilmente.Posso ridefinire una macro C++ e poi definirla?

Mantenere il mio include nel giusto ordine non è difficile il più delle volte, ma può diventare complicato quando si ha una classe JUCE che include alcune altre classi e da qualche parte sulla catena un file include Boost, e se c'è ne i file prima che servisse un JUCE includono che sei nei guai.

mio iniziale speranza al fixing questo doveva

#undef T 

prima di qualsiasi include per Boost. Ma il problema è che se non lo ri-definisco, allora un altro codice si confonde che "T" non è dichiarato.

Allora ho pensato che forse avrei potuto fare un po 'circolare #define inganno in questo modo:

// some includes up here 
#define ___T___ T 
#undef T 
// include boost headers here 
#define T ___T___ 
#undef ___T___ 

Brutto, ma ho pensato che potrebbe funzionare.

Purtroppo no. Ottengo errori in luoghi con "T" come una macro che

'___T___' was not declared in this scope. 

C'è un modo per rendere questi due biblioteche funzionano in modo affidabile insieme?

+0

Perché si sta definendo __T__ su T e quindi si deseleziona immediatamente T (e viceversa in basso)? –

+0

Immagino di poter risolvere il problema cercando la definizione originale e ridefinendo il concetto, ma preferirei avere qualcosa di più universale e affidabile. – Aftermathew

+0

Jim non sono sicuro se la formattazione abbia reso la tua domanda più difficile da capire, ma ho pensato che fosse pulito nella mia domanda? Pensi di poter riformulare la tua domanda? – Aftermathew

risposta

55

Come greyfade ha sottolineato, il tuo ___T___ trucco non funziona perché il preprocessore è una creatura piuttosto semplice. Un approccio alternativo è quello di utilizzare le direttive pragma:

// juice includes here 
#pragma push_macro("T") 
#undef T 
// include boost headers here 
#pragma pop_macro("T") 

Questo dovrebbe funzionare in MSVC++ e GCC ha aggiunto il supporto per pop_macro e push_macro per la compatibilità con esso.Tecnicamente è però dipendente dall'implementazione, ma non penso che esista un modo standard per sopprimere temporaneamente la definizione.

+1

WHOAH! E 'fantastico! Grazie Peter. – Aftermathew

+0

Sei anni dopo, è ancora così bello! Ho usato questa tecnica per abilitare una DLL Win32 a consumare uno dei suoi punti di ingresso, senza la necessità di creare un file di definizione del modulo! –

4

Allora ho pensato che forse avrei potuto fare un po 'circolare #define inganno in questo modo:

Il C preprocessore non funziona in questo modo. I simboli del preprocessore non sono definiti nello stesso senso in cui viene dato un significato al simbolo quando, , ad es., si definisce una funzione.

Potrebbe essere utile pensare al preprocessore come a un motore di sostituzione del testo. Quando viene definito un simbolo, viene considerato come testo sostitutivo, sostituendolo fino alla fine del file o finché non è indefinito. Il suo valore non è memorizzato da nessuna parte e, quindi, non può essere copiato. Pertanto, l'unico modo per ripristinare la definizione died è #undef ed è per riprodurre completamente il suo valore in un nuovopiù avanti nel codice.

Il meglio che puoi fare è semplicemente non utilizzare Boost o petizione agli sviluppatori di JUCE per non utilizzare T come macro. (O, nel peggiore dei casi, aggiustalo tu stesso cambiando il nome della macro.)

11

Puoi racchiudere la libreria incriminata in un altro include e intrappolare il #define T all'interno?

esempio:

JUICE_wrapper.h:  
#include "juice.h" 
#undef T 

main.cpp:  
#include "JUICE_wrapper.h"  
#include "boost.h" 

rest of code.... 
+0

Stavo per suggerire di aggiungere un #undef T dopo ogni #include "juice.h". Stessa idea qui ma più pulita. –

+0

Questo dovrebbe farlo. Grazie. – Aftermathew

+0

MGB, in realtà ho finito per fare quello che mi hai suggerito, ma sento come se Peter rispondesse alla domanda fatta più accuratamente. Grazie mille per il suggerimento però. – Aftermathew