Velocity Reviews

Velocity Reviews (http://www.velocityreviews.com/forums/index.php)
-   C++ (http://www.velocityreviews.com/forums/f39-c.html)
-   -   Concatination creates invalid preprocessor parameter? (http://www.velocityreviews.com/forums/t741856-concatination-creates-invalid-preprocessor-parameter.html)

Noah Roberts 01-11-2011 06:15 PM

Concatination creates invalid preprocessor parameter?
 
#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 and why?

thx

--
http://crazyeddiecpp.blogspot.com/

Alf P. Steinbach /Usenet 01-11-2011 06:23 PM

Re: Concatination creates invalid preprocessor parameter?
 
* Noah Roberts, on 11.01.2011 19:15:
> #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.


> and why?


Standard requires valid preprocessor token.

This makes it difficult to create directory paths.

Not 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).


Cheers

--
blog at <url: http://alfps.wordpress.com>

Noah Roberts 01-11-2011 08:00 PM

Re: Concatination creates invalid preprocessor parameter?
 
In article <igi77b$i32$1@news.eternal-september.org>,
alf.p.steinbach+usenet@gmail.com says...
>
> * Noah Roberts, on 11.01.2011 19:15:
> > #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.
>
>
> > and why?

>
> Standard requires valid preprocessor token.
>
> This makes it difficult to create directory paths.
>
> Not 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).
>
>
> Cheers



What's invalid about "hello(int,int)"? Why is it accepted when you
don't concat?


Comeau also gobbles it up even in strict, no-extensions mode.

--
http://crazyeddiecpp.blogspot.com/

Noah Roberts 01-11-2011 08:06 PM

Re: Concatination creates invalid preprocessor parameter?
 
In article <MPG.279656b5fd1e7f9a989695@news.mcleodusa.net>,
noneed@toemailme.com says...
>
> In article <igi77b$i32$1@news.eternal-september.org>,
> alf.p.steinbach+usenet@gmail.com says...
> >
> > * Noah Roberts, on 11.01.2011 19:15:
> > > #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.
> > > }


> What's invalid about "hello(int,int)"? Why is it accepted when you
> don't concat?
>
>
> Comeau also gobbles it up even in strict, no-extensions mode.


Actually, put a different way, if "hello(int,int)" is not a valid
preprocessor token then why is it able to form one in the first output
line in main()? There's a certain well known and often used C++ UI
library that uses this sort of syntax.



--
http://crazyeddiecpp.blogspot.com/

Alf P. Steinbach /Usenet 01-11-2011 08:20 PM

Re: Concatination creates invalid preprocessor parameter?
 
* Noah Roberts, on 11.01.2011 21:00:
> In article<igi77b$i32$1@news.eternal-september.org>,
> alf.p.steinbach+usenet@gmail.com says...
>>
>> * Noah Roberts, on 11.01.2011 19:15:
>>> #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.
>>
>>
>>> and why?

>>
>> Standard requires valid preprocessor token.
>>
>> This makes it difficult to create directory paths.
>>
>> Not 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).
>>
>>
>> Cheers

>
>
> What's invalid about "hello(int,int)"?


It consists of 6 preprocessing tokens: "hello", "(", "int", ",", "int" and ")".


> Why is it accepted when you don't concat?


16.3/10 effectively defines a preprocessor actual argument as a sequence of
preprocessing tokens. Such a sequence can contain comma tokens within
parentheses, and can otherwise not contain comma tokens.

16.3.3/3 requires the result of ## to be single preprocessing token, "otherwise
the behavior is undefined".


> Comeau also gobbles it up even in strict, no-extensions mode.


Well, with UB it can do anything. ;-)


Cheers & hth.,

- Alf

--
blog at <url: http://alfps.wordpress.com>

James Kanze 01-12-2011 11:03 AM

Re: Concatination creates invalid preprocessor parameter?
 
On Jan 11, 8:00 pm, Noah Roberts <non...@toemailme.com> wrote:
> In article <igi77b$i3...@news.eternal-september.org>,
> alf.p.steinbach+use...@gmail.com says...


> > * Noah Roberts, on 11.01.2011 19:15:
> > > #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.

> > > and why?


> > Standard 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.

> > Not 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.

> Comeau 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 **** 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


All times are GMT. The time now is 08:14 AM.

Powered by vBulletin®. Copyright ©2000 - 2014, vBulletin Solutions, Inc.
SEO by vBSEO ©2010, Crawlability, Inc.