tags:

views:

383

answers:

7

I was looking through the DXUTCore project that comes with the DirectX March 2009 SDK, and noticed that instead of making normal accessor methods, they used macros to create the generic accessors, similar to the following:

#define GET_ACCESSOR( x, y )  inline x Get##y()  { DXUTLock l; return m_state.m_##y;};
...

GET_ACCESSOR( WCHAR*, WindowTitle );

It seems that the ## operator just inserts the text from the second argument into the macro to create a function operating on a variable using that text. Is this something that is standard in C++ (i.e. not Microsoft specific)? Is its use considered good practice? And, what is that operator called?

+5  A: 

It's a preprocessing operator that concatenates left and right operands (without inserting whitespace). I don't think it's Microsoft specific.

Mehrdad Afshari
It definitely isn't. C including its preprocessor is older than MS :)
Joey
I guessed so, but it's dangerous to post things on SO you're not 100% sure of and not having read the C spec, I couldn't know for sure. ;)
Mehrdad Afshari
However, the ## preprocessor operator is not original C, and although it's old I don't think it predates Microsoft.
David Thornley
Anyhow, I *think* I have seen it in `g++` code.
Mehrdad Afshari
It is standard C. It came about because /**/ worked that way in the earliest versions of the C preprocessor. The standard decided that a comment must be replaced by a single space which cleaned up an edge case or two in the parser, but broke token pasting. So to compensate, they invented the token pasting operator and threw in the stringification operator to compensate for another change related to token replacement inside string literals. standard C++ adopted the C preprocessor essentially intact so that it was possible to parse a subset language as either C or C++.
RBerteig
+15  A: 

Token-pasting operator, used by the pre-processor to join two tokens into a single token.

Michael
+1  A: 

it's the concatenation for macro arguments i.e.

GET_ACCESSOR (int, Age);

will be expended to

inline int GetAge()  { DXUTLock l; return m_state.m_Age;};
oykuo
A: 

This isn't Standard C++, it's Standard C. Check out this Wikipedia article.

And is it a good practice? In general, I hate pre-processor macros and think they're as bad as (if not worse than) Goto.

Edit: Apparently I'm being misunderstood by what I meant by "This isn't Standard C++, it's Standard C". Many people are reading the first phrase and failing to read the second. My intent is to point out that macros were inherited by C++ from C.

Randolpho
This is standard c++, see my answer below.
GMan
I think Randolpho's point is while C++ may have it in the standard, it pre-dates C++, ie it's also a C feature (weather standard C or not).
Simeon Pilgrim
Ah, I was just relating to "This isn't Standard C++", which isn't true.
GMan
Also just like goto, in "normal" programming goto is bad, but there are places, and if your still doing "normal" programming in C you have bigger issues than goto. Testing harnesses macro's are a great use in C
Simeon Pilgrim
@Simeon: Very true. But you should still avoid them for production code. Also, I'm confused as to the two downvotes I've gotten on this post; I was not in any way inaccurate. Perhaps there are folks who love macros and goto?
Randolpho
No, I'm sure they took it the same why I did [but I didn't downvote you]. You said the words "This isn't Standard C++", which is incorrect. If you meant "This started in C", I'm sure you would have gotten no downvotes for that, because it's true.Also, macro's do have their uses. They are `Evil` and there are often better ways of getting the same results, but macro's still exist because there *are* cases when they are useful. Saying something should **never** be used is just as bad as saying they should always be used.
GMan
@GMan: You are correct, the phrase "this isn't standard C++, this is standard C" was meant to imply that macros came from C and are part of the many annoying things that C++ inherited from C. Also, please re-parse my answer and comments. I did not say "never" use macros. I said they're as bad as (possibly worse than) goto. You must have mentally inserted "never". Yes, both macros and goto have a place, but yes, they should both be avoided unless you simply cannot solve a problem without them. Even then you should be dragged kicking and screaming into choosing to use them.
Randolpho
+2  A: 

As Mehrdad said, it concatenates the operands, like:

#define MyMacro(A,B) A ## B
MyMacro(XYZ, 123) // Equivalent to XYZ123

Note that MISRA C suggests that this operand (and the # 'stringify' operand) should not be used due to the compiler dependent order of calculation.

Al
+2  A: 

It is token pasting operator allowed by Standard C++ (see 16.3.3 for details). As for good practice: using macro is not a good practice IMHO (in C++).

Kirill V. Lyadvinsky
+6  A: 

This is also standard C++, contrary to what Raldolpho stated.

Here is the relevant information:

16.3.3 The ## operator [cpp.concat]

1 A ## preprocessing token shall not occur at the beginning or at the end of a replacement list for either form of macro definition.

2 If, in the replacement list, a parameter is immediately preceded or followed by a ## preprocessing token, the parameter is replaced by the corresponding argument’s preprocessing token sequence.

3 For both object-like and function-like macro invocations, before the replacement list is reexamined for more macro names to replace, each instance of a ## preprocessing token in the replacement list (not from an argument) is deleted and the preceding preprocessing token is concatenated with the following preprocessing token. If the result is not a valid preprocessing token, the behavior is undefined. The resulting token is available for further macro replacement. The order of evaluation of ## operators is unspecified.

GMan