6

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?

Dima
  • 38,860
  • 14
  • 75
  • 115
bsruth
  • 5,372
  • 6
  • 35
  • 44

7 Answers7

17

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

Michael
  • 54,279
  • 5
  • 125
  • 144
6

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.

Community
  • 1
  • 1
GManNickG
  • 494,350
  • 52
  • 494
  • 543
5

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

Mehrdad Afshari
  • 414,610
  • 91
  • 852
  • 789
  • 5
    It definitely isn't. C including its preprocessor is older than MS :) – Joey Jul 13 '09 at 21:00
  • 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 Jul 13 '09 at 21:03
  • However, the ## preprocessor operator is not original C, and although it's old I don't think it predates Microsoft. – David Thornley Jul 13 '09 at 21:09
  • 1
    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 Jul 14 '09 at 07:18
3

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
  • 55,384
  • 17
  • 145
  • 179
  • 1
    This is standard c++, see my answer below. – GManNickG Jul 13 '09 at 21:07
  • 1
    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 Jul 13 '09 at 21:36
  • 1
    Ah, I was just relating to "This isn't Standard C++", which isn't true. – GManNickG Jul 13 '09 at 21:38
  • 1
    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 Jul 13 '09 at 21:40
  • @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 Jul 13 '09 at 22:22
  • 1
    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. – GManNickG Jul 14 '09 at 04:44
  • @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 Jul 14 '09 at 14:45
  • I don't see why they are bad. Not using macros is a sign of mismanagement also, and that's why I would never use a language like ie. C#. – Pablo Ariel Aug 28 '18 at 20:38
2

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.

DrAl
  • 70,428
  • 10
  • 106
  • 108
2

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
  • 97,037
  • 24
  • 136
  • 212
1

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;};
dmckee --- ex-moderator kitten
  • 98,632
  • 24
  • 142
  • 234
oscarkuo
  • 10,431
  • 6
  • 49
  • 62