You know, it's one of those stupid things where it takes someone else to point out what is obviously wrong.
The code was written a long time ago and always compiled without warnings under 2.95. It's only this weekend that I've ran into the problem whilst using 4 and only when compiling without the extended debugging.
Basically that set me off barking up the wrong tree

I looked at your code earlier for a while... and all I got was confused...
I just couldn't figure out what the ## was for. I just assumed it was something to do with c++(which I don't know). I have never found any use for ##.
Basically it's for concatenation in the preprocessor. I wanted to take the name of an exception and the name of the namespace or class it was nested in and turn it into either a function name or a normal exception throw depending on the compiler options. Turning it into a function name was a valid use of ##:
#DEFINE THROW_NESTED_EXCEPTION(cname, except) EXNGPrivate::throw##cname##except
when invoked thusly:
THROW_NESTED_EXCEPTION(Thread, SecurityViolationError());
generates:
EXNGPrivate::throwThreadSecurityViolationError();
That function in turn throws a Thread::SecurityViolationError after doing some other work.
Unfortunately, I got so blinded by the ## concatenation I didn't actually see what was wrong (or rather redundant) with the second form:
#DEFINE THROW_NESTED_EXCEPTION(cname, except) throw cname##::##except
which is supposed to produce
throw Thread::SecurityViolationError();
The fact is that 2.95.x was happy enough to concatenate "cname" with "::" and "::" with "except". On the face of it, regarding the preprocessor as a pure text processor, it still seems unreasonable that this gives a problem. However, it is expecting a valid
preprocessor token to be generated by the ##, not just arbitrary text.
As ejstans observed, the use of ## in the second form was completely redundant anyway. Which is why I'm now wearing a conical paper hat with a big letter D on it
