Velocity Reviews - Computer Hardware Reviews

Velocity Reviews > Newsgroups > Programming > C++ > Concatination creates invalid preprocessor parameter?

Reply
Thread Tools

Concatination creates invalid preprocessor parameter?

 
 
Noah Roberts
Guest
Posts: n/a
 
      01-11-2011
#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/
 
Reply With Quote
 
 
 
 
Alf P. Steinbach /Usenet
Guest
Posts: n/a
 
      01-11-2011
* 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>
 
Reply With Quote
 
 
 
 
Noah Roberts
Guest
Posts: n/a
 
      01-11-2011
In article <igi77b$i32$(E-Mail Removed)-september.org>,
(E-Mail Removed) 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/
 
Reply With Quote
 
Noah Roberts
Guest
Posts: n/a
 
      01-11-2011
In article <(E-Mail Removed)>,
http://www.velocityreviews.com/forums/(E-Mail Removed) says...
>
> In article <igi77b$i32$(E-Mail Removed)-september.org>,
> (E-Mail Removed) 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/
 
Reply With Quote
 
Alf P. Steinbach /Usenet
Guest
Posts: n/a
 
      01-11-2011
* Noah Roberts, on 11.01.2011 21:00:
> In article<igi77b$i32$(E-Mail Removed)-september.org>,
> (E-Mail Removed) 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>
 
Reply With Quote
 
James Kanze
Guest
Posts: n/a
 
      01-12-2011
On Jan 11, 8:00 pm, Noah Roberts <(E-Mail Removed)> wrote:
> In article <igi77b$(E-Mail Removed)-september.org>,
> (E-Mail Removed) 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
 
Reply With Quote
 
 
 
Reply

Thread Tools

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off
Trackbacks are On
Pingbacks are On
Refbacks are Off


Similar Threads
Thread Thread Starter Forum Replies Last Post
The ole Repetion != Concatination pitfall JChG Python 1 04-19-2010 04:48 AM
Preprocessor concatination of defines Jakob Simon-Gaarde C++ 4 07-02-2004 03:17 AM
String concatination Rajika Somasiri ASP .Net Web Controls 2 02-23-2004 09:12 AM
String concatination Rajika Somasiri ASP .Net Web Controls 1 02-09-2004 05:41 AM
Writing a listbox value to an html link concatination Crystal ASP General 3 07-09-2003 05:50 PM



Advertisments