Post by Noah RobertsPost by Alf P. Steinbach /UsenetPost by Noah Roberts#define STR_HELPER(s) #s
#define STRINGIZE(s) STR_HELPER(s)
// BOOST_PP_CAT also fails for same reason.
#define MACRO(s1,s2) STRINGIZE(s1 ## s2)
#include<iostream>
int main()
{
std::cout<< STRINGIZE(hello(int,int))<< std::endl; // fine.
std::cout<< MACRO(hello, (int,int))<< std::endl; // error.
}
Error = concatination of 'hello' and '(' creates invalid preprocessor
token.
Both versions work fine in MSVC++. G++ hates it.
What's the deal? Who's wrong
Visual C++ wrong, g++ right.
Both are right. It's undefined behavior, and anything the
compiler does when there is undefined behavior is right.
Post by Noah RobertsPost by Alf P. Steinbach /UsenetStandard requires valid preprocessor token.
This makes it difficult to create directory paths.
G++ solves this by allowing concatenated string literals to be
used as a directory path. Although I can't find anything in the
standard which supports this, it also works with VC++ and with
Sun CC, so I guess it's sort of a defacto standard.
Post by Noah RobertsPost by Alf P. Steinbach /UsenetNot easy to say why the proprocessor is so incredibly
primitive and limited, but consider that if it were more
powerful then it would probably be used more (which would be
undesireable).
What's invalid about "hello(int,int)"? Why is it accepted when you
don't concat?
With the "...", there's nothing wrong with it. Without the
"...", as the results of ##, it's not a single token, so
undefined behavior results.
Post by Noah RobertsComeau also gobbles it up even in strict, no-extensions mode.
It used to be a traditional solution; preprocessors generally
substitute (and concatenate) text strings, not tokens. I think
g++ introduced the check (it worked with older versions of gcc)
just to piss people off. Formally, it's undefined behavior: the
C committee wanted to allow preprocessors to work at the token
level. But in practice, no preprocessor has ever done this, and
your example had always worked, everywhere. Until gcc decided
to break it.
As Alf pointed out, it's a pain when it comes to generating
include paths. (In my own code, I use things like:
#include GB_dependentInclude(syst,"someFile.h")
to pick up an include which depends on the system, for example.
And there's a fair amount of token pasting going on in
GB_dependentInclude. Except that I don't token paste;
I concatenate string literals. Which shouldn't work, if you
read the standard literally, but in fact does, at least with all
of the compilers I've encountered.)
--
James Kanze