views:

305

answers:

3

I am using both the JUCE Library and a number of Boost headers in my code. Juce defines "T" as a macro (groan), and Boost often uses "T" in it's template definitions. The result is that if you somehow include the JUCE headers before the Boost headers the preposser expands the JUCE macro in the Boost code, and then the compiler gets hopelessly lost.

Keeping my includes in the right order isn't hard most of the time, but it can get tricky when you have a JUCE class that includes some other classes and somewhere up the chain one file includes Boost, and if any of the files before it needed a JUCE include you're in trouble.

My initial hope at fixing this was to

#undef T

before any includes for Boost. But the problem is, if I don't re-define it, then other code gets confused that "T" is not declared.

I then thought that maybe I could do some circular #define trickery like so:

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

Ugly, but I thought it may work.

Sadly no. I get errors in places using "T" as a macro that

'___T___' was not declared in this scope.

Is there a way to make these two libraries work reliably together?

+1  A: 

I then thought that maybe I could do some circular #define trickery like so:

The C Preprocessor doesn't work this way. Preprocessor symbols aren't defined in the same sense that a symbol is given meaning when, e.g., you define a function.

It might help to think of the preprocessor as a text-replace engine. When a symbol is defined, it's treated as a straight-up text-replace until the end of the file or until it's undefined. Its value is not stored anywhere, and so, can't be copied. Therefore, the only way to restore the definition of T after you've #undefed it is to completely reproduce its value in a new #define later in your code.

The best you can do is to simply not use Boost or petition the developers of JUCE to not use T as a macro. (Or, worst case, fix it yourself by changing the name of the macro.)

greyfade
+5  A: 

Can you wrap the offending library in another include and trap the #define T inside?

eg:

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

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

 rest of code....
Martin Beckett
I was about to suggest just adding an #undef T after every #include "juice.h". Same idea here but cleaner.
caspin
This should do it. Thanks.
Aftermathew
MGB, I actually ended up doing what you suggested But feel like peter answered the question asked more accurately. Thanks much for the suggestion though.
Aftermathew
I was looking for the push/pop macro to check exactly what it did but I couldn't find it! It's silly it having "_macro" on the end
Martin Beckett
+7  A: 

As greyfade pointed out, your ___T___ trick doesn't work because the preprocessor is a pretty simple creature. An alternative approach is to use pragma directives:

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

That should work in MSVC++ and GCC has added support for pop_macro and push_macro for compatibility with it. Technically it is implementation-dependent though, but I don't think there's a standard way of temporarily suppressing the definition.

Peter
WHOAH! That is so cool! Thanks Peter.
Aftermathew