23

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

Say I have some code that uses the name BLAH for a variable. Suppose BLAH is a common preprocessor definition in many standard header files (defined as 10), so if my file is included after any of them, the code breaks because BLAH is transformed into 10; therefore, I must #undef BLAH. But also other headers may depend on BLAH, so I must restore BLAH to it's original value after my header is done. Is it possible to do something like this:

#ifdef BLAH
#define BLAH_OLD BLAH
#undef BLAH
#endif

... code ...

// restore BLAH to 10
#ifdef BLAH_OLD
#define BLAH BLAH_OLD
#end

? This doesn't work of course, because BLAH is not expanded to 10. I have tried doing something like

#define EXPAND_AGAIN(x) x
#define EXPAND(x) EXPAND_AGAIN(x)
#define BLAH_OLD EXPAND(BLAH)

but that doesn't work either, since EXPAND is taken literally and not expanded. I am using MSVC 2008/2010, but it would be lovely if the solution would work on most other compilers too.

Community
  • 1
  • 1
Epro
  • 673
  • 2
  • 7
  • 9
  • 3
    Have you considered changing your variable naming? – Paul Sonier Nov 08 '10 at 21:18
  • Change the name of your variable; terrible convention you've got going on there if this is a problem. And how about instead of "let's say" you say "here's the actual problem I'm trying to solve." – GManNickG Nov 08 '10 at 21:34
  • 1
    You do realize the it has been a convention from nearly the beginning of time that identifiers that are all caps are reserved for use by the pre-processor (to avoid things like this). – Martin York Nov 08 '10 at 21:49

4 Answers4

37

Yes, given that your compiler supports the push/pop macro directives (visual c++, gcc, llvm all do):

#define BLAH 10

#pragma push_macro("BLAH")
#undef BLAH

#define BLAH 5

...

#pragma pop_macro("BLAH")
yonilevy
  • 5,320
  • 3
  • 31
  • 27
4

Unfortunately the preprocessor doesn't support a stack of definitions.

The Boost preprocessor library makes the preprocessor do things you'd never imagine it could do (like effectively variadic macros in C++98), but is bound by the inherent limitations of the preprocessor -- so, no can do, sorry.

The only known half-way remedy is to reserve ALL_UPPERCASE_IDENTIFIERS for macros, and consistently always use them for macros. It reduces the name collision problem somewhat. Unfortunately the C standard library defines a number of lowercase macros, or allows for their existence, like e.g. assert, but they are just a few.

From a practical point of view the main problem is in Windows programming, where Microsoft's [windows.h] header defines zillions of non-uppercase macros, including, by default, min and max which conflict with the C++ standard library.

So, for Windows C++ programming, always define NOMINMAX before including [windows.h].

Cheers & hth.,

Cheers and hth. - Alf
  • 142,714
  • 15
  • 209
  • 331
  • thanks for `NOMINMAX`, but there is `#pragma push_macro` at least – Sergei Krivonos Jan 27 '17 at 21:22
  • @Sergei: Yes, `#pragma push_macro` is [the accepted solution in the duplicate question](http://stackoverflow.com/a/1794089/464581). But as I noted in a comment on another answer for this question, it was non-standard in 2010. I believe it's still non-standard, although it's supported by, at least, Visual C++, g++ and clang. – Cheers and hth. - Alf Jan 27 '17 at 23:59
0

I used to believe that the very same trick you tried does work, as I used to use it myself. But I eventually learned that it actually does not work at all. The simple answer is NO, you cannot save a define's current value, change it, and then restore the old value. The preprocessor simply does not work that way. Once you define a new value, the old value is gone.

Remy Lebeau
  • 555,201
  • 31
  • 458
  • 770
-3

One trick that works for me is to use an enum in the class.

class foo
{
public:
  enum { blah = 10 } myenum;
}

Then you can just use

foo:blah

when you need '10'.

Since it's part of the class then other uses of 'blah' won't conflict and you save all that def'ing and undef'ing.

Jay
  • 13,803
  • 4
  • 42
  • 69
  • 1
    What? `#define blah 0`, breaks your code. – GManNickG Nov 08 '10 at 21:38
  • -1 for Advice That Generally Does Not Work. If "blah" is already defined as a preprocessor macro, the enum definition will most probably be syntactically ill-formed. The only possibility of passing is when "blah" is defined as a valid identifier. Cheers, – Cheers and hth. - Alf Nov 08 '10 at 21:39
  • replace the macro with the enum and all the issues of dealing with macro collisions go away. It won't fix 'pushing' a value. – Jay Nov 09 '10 at 14:52
  • 1
    I don't think this will help with, for example, STL `max`. Its a function nearly everywhere except Windows, which defines it as a macro (even in VS2015/C++11). See [PRB: Using STL in Windows Program Can Cause Min/Max Conflicts](https://support.microsoft.com/en-us/kb/143208). – jww Aug 02 '15 at 14:08