15

My mental model of how the preprocessor works is apparently incomplete, and this is driving me crazy.

I want to concatenate two tokens, but the second token should be expanded first.

#define ANSWER 42

#define FOO foo_ ## ANSWER

Here, FOO expands to foo_ANSWER, but I want it to be foo_42. So I define a MERGE macro in the hopes that this would somehow expand the arguments before concatenation:

#define MERGE(x, y) x ## y

#define BAR MERGE(bar_, ANSWER)

But BAR still expands to bar_ANSWER instead of bar_42. So I define another macro HELPER:

#define HELPER(x, y) MERGE(x, y)

#define BAZ HELPER(baz_, ANSWER)

And now BAZ is successfully expanded to baz_42. At the moment, this seems like magic to me.

Can anyone explain this behavior to me? How do the expansion rules work exactly?

a3f
  • 8,517
  • 1
  • 41
  • 46
fredoverflow
  • 256,549
  • 94
  • 388
  • 662
  • I'm sorry to say that I'd also made a possible duplicated question of this same issue. I wonder why don't this behaviour is not documented clearly. I mean the algorithm that preprocessor operates. – sandun dhammika May 16 '13 at 20:57
  • @sandundhammika: Its pretty clearly documented in the spec -- section 6.10.3 -- though there are a number of undefined behavior corners. – Chris Dodd Apr 18 '15 at 19:14

2 Answers2

9

Read the answer to your question here:

The problem is that when you have a macro replacement, the preprocessor will only expand the macros recursively if neither the stringizing operator # nor the token-pasting operator ## are applied to it. So, you have to use some extra layers of indirection, you can use the token-pasting operator with a recursively expanded argument

Community
  • 1
  • 1
Simone
  • 11,655
  • 1
  • 30
  • 43
  • And this is why there is `BOOST_PP_CAT` :) – Matthieu M. Nov 26 '10 at 17:07
  • The quote above is not correct, or at least not complete. To expand the macro, you need TWO levels of indirection (tested in VS2017, and reports of the same in Gnu cpp). I would like to hear an explanation of why the 2nd level of indirection is necessary. Having just one level indirection, without any "#" or "##", does not expand the macro. But the 2nd level does. – Gabe Halsmer Nov 16 '17 at 14:35
3

Token concatenation does not expand macros when performing concatenation [ref].

To get past this, you use a level of indirection, and get the preprocessor to expand the macros before the concatenation.

#define STEP1(x, y)    STEP2(x, y)    // x and y will be expanded before the call to STEP2
#define STEP2(x, y)    x ## y         // x and y will not be expanded, just pasted
Ziffusion
  • 8,779
  • 4
  • 29
  • 57