benwad
benwad

Reputation: 6604

Concatenating two strings in macro definition (Clang)

I'm working on some code that was originally made in MSVC and I'm trying to get it to compile on Clang (using Xcode). The code I've got is something like this:

#define DO_MAPPING(x,y,z)\
    myMaps[map##x] = GetTex( #x##"Map" );\
    myRemaps[map##x] = GetHandle( #x##"Remap" );

Currently I'm getting a build error saying that pasting formed the string "Height""Map", where I really want "HeightMap". This code works on MSVC, is there something about Clang's macro syntax that means this kind of thing needs to be written differently?

Upvotes: 0

Views: 2113

Answers (4)

Shahbaz
Shahbaz

Reputation: 47603

In C, "X""Y" is equivalent to "XY". However, when you write such a thing in a macro:

str1##str2

you are telling the lexer to concat the two as one token. "X""Y" is actually two tokens that are concatenated by the lexer1, while "X"##"Y" is supposed to be one token (which is not a valid token).

What you need is to simply drop the ##:

#define DO_MAPPING(x,y,z)\
    myMaps[map##x] = GetTex( #x "Map" );\
    myRemaps[map##x] = GetHandle( #x "Remap" );

1 Or the semantics analyzer, depending on the implementation


Typically, the regex matching a string looks like this (simplified):

"(a|\b)*"

(assume a is a list of all characters that don't need to be escaped and b is the others). Probably, for MSVC, it is defined like this:

"(a|\b)*"s*+

(s is whitespace)

This means that MSVC probably sees "X" "Y" as one token instead of two.

Upvotes: 3

PiotrNycz
PiotrNycz

Reputation: 24440

Just use (#x "Map") in place of #x##"Map". It should work in C++. E.g. this is perfectly valid: ("B" "Map") and evaluates to "BMap".

Upvotes: 2

Synxis
Synxis

Reputation: 9388

Try this instead:

#define DO_MAPPING(x,y,z)\
    myMaps[map##x] = GetTex( #x "Map" );\
    myRemaps[map##x] = GetHandle( #x "Remap" );

Two string litterals are automatically concatenated by the compiler.

Upvotes: 1

orlp
orlp

Reputation: 118006

Note that "Height""Map" actually is the same as "HeightMap" when parsed. So you can simply use this:

#define DO_MAPPING(x,y,z)\
    myMaps[map##x] = GetTex( #x "Map" );\
    myRemaps[map##x] = GetHandle( #x "Remap" );

Upvotes: 1

Related Questions