Is there a way to do a #define inside of another #define?

C++C Preprocessor

C++ Problem Overview


I know that I am trying to shoot myself in the leg ;) However, it will allow me to make the rest (big amount) of code smaller and more readable.

Is there any tricky way to create preprocessor macro inside of another preprocessor macro?

Here is the example, what I am looking for. My real scenario is more complex

// That's what I want to do and surely C++ doesn't like it.
#define MACROCREATER(B) #define MACRO##B B+B

void foo()
{
 MACROCREATOR(5) // This should create new macro (#define MACRO5 5+5)

 int a = MACRO5; // this will use new macro
}

C++ Solutions


Solution 1 - C++

The C++ Standard says (16.3.4.3):

> The resulting completely > macro-replaced preprocessing token > sequence [... of the macro expansion...] is not processed as a > preprocessing directive even if it > resembles one...

So no, there is no 'official' way of achieving what you want with macros.

Solution 2 - C++

No. Even if a macro expands into something that looks like a preprocessing directive, the expansion is not evaluated as a preprocessing directive.

Solution 3 - C++

As a supplement to the answers above, if you really wanted to pre-process a source file twice—which is almost definitely not what you actually want to do—you could always invoke your compiler like this:

g++ -E input.cpp | g++ -c -x c++ - -o output.o

That is, run the file through the preprocessor, then run the preprocessed output via pipe through a full compilation routine, including a second preprocessing step. In order for this to have a reasonably good chance of working, I'd imagine you'd have to be rather careful in how you defined and used your macros, and all in all it would most likely not be worth the trouble and increased build time.

If you really want macros, use standard macro-based solutions. If you really want compile-time metaprogramming, use templates.

On a slightly related note, this reminds me of the fact that raytracing language POV-Ray made heavy use of a fairly complex preprocessing language, with flow-control directives such as #while that allowed conditional repetition, compile-time calculations, and other such goodies. Would that it were so in C++, but it simply isn't, so we just do it another way.

Solution 4 - C++

No. The pre-processor is single-pass. It doesn't re-evaluate the macro expansions.

Solution 5 - C++

As noted, one can #include a particular file more than once with different macro definitions active. This can make it practical to achieve some effects that could not be practically achieved via any other means.

As a simple example, on many embedded systems pointer indirection is very expensive compared to direct variable access. Code which uses a lot of pointer indirection may very well be twice as large and slow as code which simply uses variables. Consequently, if a particular routine is used with two sets of variables, in a scenario where one would usually pass in a pointer to a structure and then use the arrow operator, it may be far more efficient to simple put the routine in its own file (I normally use extension .i) which is #included once without macro _PASS2 defined, and a second time with. That file can then #ifdef _PASS2/#else to define macros for all the variables that should be different on the two passes. Even though the code gets generated twice, on some micros that will take less space than using the arrow operator with passed-in pointers.

Solution 6 - C++

Take a look at m4. It is similar to cpp, but recursive and much more powerful. I've used m4 to create a structured language for assemblers, e.g.

  cmp r0, #0
  if(eq)
    mov r1, #0
  else
    add r1, #1
  end

The "if", "else", and "end" are calls to m4 macros I wrote that generate jumps and labels, the rest is native assembly. In order to nest these if/else/end constructs, you need to do defines within a macro.

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionVictor RoninView Question on Stackoverflow
Solution 1 - C++hkaiserView Answer on Stackoverflow
Solution 2 - C++James McNellisView Answer on Stackoverflow
Solution 3 - C++Jon PurdyView Answer on Stackoverflow
Solution 4 - C++Laurence GonsalvesView Answer on Stackoverflow
Solution 5 - C++supercatView Answer on Stackoverflow
Solution 6 - C++Jonathan EngdahlView Answer on Stackoverflow