6

Suppose you have the macro

#define TOKEN1 <arbitrary sequence of characters>

But suppose, in a few cases, you really mean TOKEN1, not what it has been defined to. Is there a trick which allows the pre-processed file to contain "TOKEN1", without #undef'ining TOKEN1, and with TOKEN1 appearing after it has been #define'd?

Context:

I am working on adding memory tracking by redefining new. But, I am running into the problem that I have also overloaded operator new in several classes, and it is awkward to have to undefine new in all these places, and then re-include the header that does the magic after.

a3f
  • 8,517
  • 1
  • 41
  • 46
Vigabrand
  • 161
  • 6
  • there is no way, the preprocessor blindly replaces the text before any compilation takes place, so if you don't `#undef` it, you cannot ask the compile to just ignore the preprocessor. – vsoftco Jul 22 '14 at 02:25
  • @vsoftco There is no way to write a macro which evaluates to TOKEN1, which the preprocessor doesn't then evaluate? – Vigabrand Jul 22 '14 at 02:28
  • 3
    Well, I guess you can do `#define TOKEN2 TOKEN1`, then when you write `TOKEN1` the preprocessor will replace it with `TOKEN2`, and then replace that with `TOKEN1`, at which point it will stop replacing... – T.C. Jul 22 '14 at 02:50
  • @T.C.: Looks like you posted this comment at the same time I answered. Note that it works so long as `TOKEN2` had not already been redefined to something else. – jxh Jul 22 '14 at 03:02
  • Hence the common coding convention of using different naming conventions for macros and actual language identifiers. – Keith Jul 22 '14 at 03:05
  • Note that `#define new`... causes undefined behaviour, there is surely a better solution than that (even if it does seem to work). For example you could add tracking to your `T::operator new()` function that is conditionally enabled, and/or replace the global allocators. – M.M Jul 22 '14 at 04:02
  • @MattMcNabb For the tracking to be useful it needs to store file and line number – Vigabrand Jul 22 '14 at 04:07
  • sounds like an interesting topic for a question post :) – M.M Jul 22 '14 at 04:09
  • Actually I got the idea from this question:http://stackoverflow.com/questions/6261201/how-to-find-memory-leak-in-c-code-project – Vigabrand Jul 22 '14 at 06:24

4 Answers4

3

A general approach would be to place all code that had the requirement of "do not replace TOKEN1" into a single solitary source file, and then not include the header file that defines the replacement into that file.

If the arbitrary sequence of characters were a single token (as it was before you edited your question), you can do this:

#define TOKEN2 TOKEN1
if (you_really_mean(TOKEN1)) {
    //...
}
#undef TOKEN2

But, this solution is limited, since you run into problems if TOKEN2 had already been redefined to something else before.

If you have full control over what is being defined and what not, you can do this:

#define TOKEN1 TOKEN2
#define TOKEN2 <arbitrary sequence formerly assigned to TOKEN1>

Then, in your code to escape TOKEN1:

#undef TOKEN1
//... code where you don't want TOKEN1 replaced
#define TOKEN1 TOKEN2

For your particular problem for handling overloaded new, I find that largely, overloaded new implementations are mostly identical (because they are usually just boiler plate code changing the allocator to use something other than system heap). If this is the case for you as well, you can put the overload definitions into an unguarded header file. This header file can #undef the definition of new and then redefine it again after the overload definitions.

Then any class can include this header file.

jxh
  • 69,070
  • 8
  • 110
  • 193
  • Another way to go would be to require the project to use some mechanism other than `new` to allocate memory, and that mechanism has your debugging stuff. Then you can try to disable users of the regular `new` allocator. See [this question](http://stackoverflow.com/q/18365804/315052). – jxh Jul 22 '14 at 04:26
3

There's a GCC/Clang extension that can do something like this (I think MSVC has a similar one too), if you have access to language extensions:

#define TOKEN1 123
#pragma push_macro("TOKEN1")
#undef TOKEN1
TOKEN1     // inserts TOKEN1 into the program text
#pragma pop_macro("TOKEN1")
TOKEN1     // inserts 123 into the program source text

It allows you to save and restore macro definitions independently of the input text, for just such a purpose.

jxh's solution is cleaner, though; but fundamentally, you should be rethinking whatever your reasons are for trying to make a single term have multiple meanings. The macro language is supposed to help you abstract elements of a single, unified program; not create two competing, fighting sources in one file.

Community
  • 1
  • 1
Alex Celeste
  • 12,824
  • 10
  • 46
  • 89
0

You can temporarily bypass the definition by adding the "reverse" macro, if <arbitrary sequence of characters> is valid as a macro invocation (it has the form of an identifier or id( args )).

#define TOKEN1 arbitrary_identifier

TOKEN1 // expands to arbitrary_identifier

...
// Now we really want to say TOKEN1

#define arbitrary_identifier TOKEN1

TOKEN1 // TOKEN1 => arbitrary_identifier => TOKEN1 and stop expanding

// Finished with TOKEN1 override

#undef arbitrary_identifier

TOKEN1 // expands to arbitrary_identifier again.

I don't think a workaround exists for a truly arbitrary sequence of expansion tokens. And, this workaround is really no better than #undef TOKEN1 and then doing #define again, since the bypass code still needs to know the expansion.

Potatoswatter
  • 134,909
  • 25
  • 265
  • 421
0

If you have access to change the definition of TOKEN1 you could make it:

#define TOKEN1() arbitrary stuff...

Then TOKEN1 not followed by ( does not undergo expansion. Even if there is a following ( you can stil suppress it by writing (TOKEN1) .

M.M
  • 138,810
  • 21
  • 208
  • 365