|
||||
|
Section 39:
|
[39.6] What should be done with macros that need to paste two tokens together? Updated!
[Recently capitalized macro name3() to NAME3() to prevent name-collisions. Click here to go back to the beginning of the "chain" of recent changes]
Groan. I really hate macros. Yes they're useful sometimes, and yes I use them. But I always wash my hands afterwards. Twice. Macros are evil in 4 different ways: evil#1, evil#2, evil#3, and evil#4. Okay, here we go again, desperately trying to make an inherently evil thing a little less evil. First, the basic approach is use the ISO/ANSI C and ISO/ANSI C++ "token pasting" feature: ##. On the surface this would look like the following: Suppose you have a macro called "MYMACRO", and suppose you're passing a token as the parameter of that macro, and suppose you want to concatenate that token with the token "Tmp" to create a variable name. For example, the use of MYMACRO(Foo) would create a variable named FooTmp and the use of MYMACRO(Bar) would create a variable named BarTmp. In this case the naive approach would be to say this:
#define MYMACRO(a) \
/*...*/ a ## Tmp /*...*/
However you need a double layer of indirection when you use ##.
Basically you need to create a special macro for "token pasting" such as:
#define NAME2(a,b) NAME2_HIDDEN(a,b) #define NAME2_HIDDEN(a,b) a ## bTrust me on this — you really need to do this! (And please nobody write me saying it sometimes works without the second layer of indirection. Try concatenating a symbol with __LINE__ and see what happens then.) Then replace your use of a ## Tmp with NAME2(a,Tmp):
#define MYMACRO(a) \
/*...*/ NAME2(a,Tmp) /*...*/
And if you have a three-way concatenation to do (e.g., to paste three tokens
together), you'd create a NAME3() macro like this:
#define NAME3(a,b,c) NAME3_HIDDEN(a,b,c) #define NAME3_HIDDEN(a,b,c) a ## b ## c |
|||