Carbon
Carbon

Reputation: 3943

How do I add whitespace to a concat preprocessor macro?

Given the below, how can I get something that yields ONE TWO THREE? I can't seem to figure out what to put in ?? to yield the intended concat behavior. You can't seem to #define a single space.

#include <iostream>
#define STRINGIFY(x) #x
#define STRINGIFYMACRO(y) STRINGIFY(y)

#define CONCAT2(X,Y) X ##  Y
#define CONCAT(X,Y) CONCAT2(X,Y)

#define CAT \
ONE     \
TWO


#define DOG \
THREE

#define BAT CONCAT(CONCAT(CAT,?? ),DOG)

int main()
{
    std::cout << STRINGIFYMACRO(BAT) << std::endl;
    return 0;
}

Upvotes: 3

Views: 3183

Answers (1)

rici
rici

Reputation: 241721

The ## operator is used to combine two consecutive tokens. It cannot be used to combined things that are not tokens (such as whitespace), nor can it be used if the result is not a valid (preprocessing) token.

In other words, don't use ## to combine strings. That's not what it is for, and it won't work.

Remember that in C++, consecutive strings will be concatenated by the compiler. So there is normally no need to concatenate the contents of the string. Even if you had to concatenate the contents, you could do that without token concatenation because the contents of a string are not a token. (This is only necessary if you are trying to create a computed #include filename from multiple components.)

One other useful thing to know is that whitespace inside a macro replacement (not at either end) is reduced to a single space character, which is preserved by the stringify operator.

So if you're OK with the single space character, you can just do this:

#include <iostream.h>
#define STRINGIFY(x) #x
#define STRINGIFY_EXPANDED(x) STRINGIFY(x)

#define CAT ONE TWO
#define DOG THREE
#define BAT CAT DOG

int main() {
  std::cout << STRINGIFY_EXPANDED(BAT) << '\n';
  return 0;
}

Try it online!

Otherwise, you could stringify in pieces and concatenate the pieces as desired:

#define DOG STRINGIFY(ONE) "   " STRINGIFY(TWO)
#define CAT STRINGIFY(THREE)
#define BAT DOG "\t" CAT

Try it online!

Upvotes: 3

Related Questions