Welcome, Guest. Please login or register.

Author Topic: Dear God, WHY?!?!  (Read 7557 times)

Description:

0 Members and 1 Guest are viewing this topic.

Offline ejstans

  • Newbie
  • *
  • Join Date: Jun 2009
  • Posts: 48
    • Show all replies
Re: Dear God, WHY?!?!
« on: August 08, 2009, 10:52:22 PM »
Quote from: Karlos;518506
Tried that, no joy.

After some experimentation I have discovered that pretty much any C/C++ operator (especially ., -> etc) doesn't like being used in ## concatenation. Which is completely stupid.

IMO, that's totally and utterly broken. It should not be up the the preprocessor to dictate what constitutes "valid" output from concatenating two pieces of text. It should just do the job and if the result is meaningless garbage, that's up to the compiler to diagnose.

It isn't the first issue I have had with gcc 4's preprocessor. It has issues with computed includes too.

You are in undefined behavior-land. From the C++98 standard:

"16.3.3 The ## operator
 [...]
 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 preprocessor 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."

The important part here is "If the result is not a valid preprocessing token, the behavior is undefined". Gcc is rather nice to point this out :)

Let's look at your fix:

#define PP_CONCAT(a, b, c) a##c::c##b

This (seemingly) works because 'a' and 'c' are concatenated (and 'c' and 'b' likewise) and since you pass in an empty argument the result is simply 'a' (and 'b') which is a valid preprocessing token. Or is it? Actually, passing in an empty argument results in undefined behaviour, so this is not a good fix...

But what if we suppose passing an in empty argument was in fact well-defined and acted like above? The result would simply be the same as:

#define PP_CONCAT(a, b) a::b

So why mix in the concatenting operator? :)
"It is preferable not to travel with a dead machine."

A500 1.3 / 512KiB slowmem / GVP HD8 w/ 8MiB fastmem & 52MB HDD
A600 2.05 / 1GB SSD
A1200 3.0 / Blizzard 1200/4 w/ 68882 @ 33MHz / 1GB SSD
A1200T 3.0 / Apollo 1260 w/ 68EC060 @ 50MHz & 16 MiB fastmem / 4GB SSD
 

Offline ejstans

  • Newbie
  • *
  • Join Date: Jun 2009
  • Posts: 48
    • Show all replies
Re: Dear God, WHY?!?!
« Reply #1 on: August 08, 2009, 11:21:05 PM »
Actually, not clearer...

Is the second macro the following macro:

#define THROW_NESTED_EXCEPTION(cname, except) throw cname##::##except

If so, the argument from the synthetic example applies here as well: Why the ##-operator? No need for it. Try:

#define THROW_NESTED_EXCEPTION(cname, except) throw cname::except
"It is preferable not to travel with a dead machine."

A500 1.3 / 512KiB slowmem / GVP HD8 w/ 8MiB fastmem & 52MB HDD
A600 2.05 / 1GB SSD
A1200 3.0 / Blizzard 1200/4 w/ 68882 @ 33MHz / 1GB SSD
A1200T 3.0 / Apollo 1260 w/ 68EC060 @ 50MHz & 16 MiB fastmem / 4GB SSD