Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Can I redefine a C++ macro then define it back?

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 preprocessor 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?

like image 524
Aftermathew Avatar asked Nov 24 '09 23:11

Aftermathew


People also ask

Can I redefine a macro?

Redefining a macro is simply using the #define directive to provide a new macro body for an existing macro definition. If the redefinition is identical to the original definition, the compiler goes on without emitting any type of diagnostic message.

Can you change macros in C?

You can't. Macros are expanded by the Preprocessor, which happens even before the code is compiled.

How do you override a defined macro?

You can use the #undef preprocessor directive to undefine (override) a previously defined macro.

Can define value be changed?

Yes, you can change a #define value.


2 Answers

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.

like image 65
Peter Avatar answered Oct 02 '22 21:10

Peter


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.... 
like image 39
Martin Beckett Avatar answered Oct 02 '22 20:10

Martin Beckett