2009-11-24 7 views
35

Estoy usando tanto la Biblioteca JUCE como una serie de encabezados Boost en mi código. Juce define "T" como una macro (gemido), y Boost a menudo usa "T" en sus definiciones de plantilla. El resultado es que si de alguna manera incluye los encabezados JUCE antes de los encabezados de Boost, el preprocesador expande la macro JUCE en el código de Boost, y luego el compilador se pierde irremediablemente.¿Puedo redefinir una macro de C++ y luego definirla de nuevo?

Mantener mi inclusión en el orden correcto no es difícil la mayor parte del tiempo, pero puede ser complicado cuando tienes una clase JUCE que incluye algunas otras clases y en algún lugar de la cadena un archivo incluye Boost, y si alguno los archivos antes de necesitar un JUCE incluyen que estás en problemas.

Mi esperanza inicial en la fijación de este era

#undef T 

antes de cualquier incluye, por Boost. Pero el problema es que si no lo vuelvo a definir, entonces se confunde el otro código y no se declara "T".

Entonces pensé que tal vez podría hacer algo de engaño #define circular de este modo:

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

feo, pero pensé que podría funcionar.

Lamentablemente no. Recibo errores en lugares usando "T" como una macro que

'___T___' was not declared in this scope. 

¿Hay una manera de hacer estas dos bibliotecas funcionan de forma fiable juntos?

+0

¿Por qué define __T__ a T y luego indefiniendo inmediatamente T (y viceversa a continuación)? –

+0

Creo que puedo solucionarlo buscando la definición original y redefiniéndola, pero prefiero algo más universal y confiable. – Aftermathew

+0

Jim no estoy seguro de si el formato hizo que su pregunta fuera más difícil de entender, ¿pero pensé que estaba limpia en mi pregunta? ¿Crees que puedes reformular tu pregunta? – Aftermathew

Respuesta

55

Como greyfade señaló, su ___T___ truco no funciona debido a que el preprocesador es una criatura bastante simple. Un enfoque alternativo es utilizar directivas Pragma:

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

que debería funcionar en MSVC++ y GCC ha añadido soporte para pop_macro y push_macro para la compatibilidad con ella.Técnicamente, depende de la implementación, pero no creo que haya una forma estándar de suprimir temporalmente la definición.

+1

¡WHOAH! ¡Eso es tan cool! Gracias Peter. – Aftermathew

+0

¡Seis años después, todavía es genial! Utilicé esta técnica para permitir que una DLL Win32 consuma uno de sus propios puntos de entrada, ¡sin necesidad de crear un archivo de definición de módulo! –

4

Entonces pensé que tal vez podría hacer algo de engaño #define circular de este modo:

El preprocesador C no funciona de esta manera. Los símbolos de preprocesador no están definidos en el mismo sentido en que se da un significado a un símbolo cuando, p. Ej., define una función.

Puede ser útil pensar en el preprocesador como un motor de reemplazo de texto. Cuando se define un símbolo, se trata como un reemplazo de texto directo hasta el final del archivo o hasta que no esté definido. Su valor no se almacena en ningún lado y, por lo tanto, no se puede copiar. Por lo tanto, la única forma de restaurar la definición de T una vez que haya #undef ed es reproducir completamente su valor en un nuevo #define más adelante en su código.

Lo mejor que puedes hacer es simplemente no usar Boost o solicitar a los desarrolladores de JUCE que no usen T como una macro. (O, en el peor de los casos, arréglalo cambiando el nombre de la macro.)

11

¿Puedes envolver la biblioteca ofensiva en otra inclusión y atrapar la #define T dentro?

por ejemplo:

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

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

rest of code.... 
+0

Estaba a punto de sugerir simplemente agregar un #undef T después de cada #include "juice.h". La misma idea aquí pero más limpia. –

+0

Esto debería hacerlo. Gracias. – Aftermathew

+0

MGB, en realidad terminé haciendo lo que sugirió Pero siento que Peter respondió la pregunta con más precisión. Muchas gracias por la sugerencia, sin embargo. – Aftermathew

Cuestiones relacionadas