Concatination creates invalid preprocessor parameter?

Discussion in 'C++' started by Noah Roberts, Jan 11, 2011.

  1. Noah Roberts

    Noah Roberts Guest

    #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/
    Noah Roberts, Jan 11, 2011
    #1
    1. Advertising

  2. * 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>
    Alf P. Steinbach /Usenet, Jan 11, 2011
    #2
    1. Advertising

  3. Noah Roberts

    Noah Roberts Guest

    In article <igi77b$i32$-september.org>,
    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, Jan 11, 2011
    #3
  4. Noah Roberts

    Noah Roberts Guest

    In article <>,
    says...
    >
    > In article <igi77b$i32$-september.org>,
    > 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/
    Noah Roberts, Jan 11, 2011
    #4
  5. * Noah Roberts, on 11.01.2011 21:00:
    > In article<igi77b$i32$-september.org>,
    > 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>
    Alf P. Steinbach /Usenet, Jan 11, 2011
    #5
  6. Noah Roberts

    James Kanze Guest

    On Jan 11, 8:00 pm, Noah Roberts <> wrote:
    > In article <igi77b$-september.org>,
    > 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 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
    James Kanze, Jan 12, 2011
    #6
    1. Advertising

Want to reply to this thread or ask your own question?

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. Jakob Simon-Gaarde

    Preprocessor concatination of defines

    Jakob Simon-Gaarde, Jul 1, 2004, in forum: C++
    Replies:
    4
    Views:
    433
    Jack Klein
    Jul 2, 2004
  2. JChG
    Replies:
    1
    Views:
    238
    Steven D'Aprano
    Apr 19, 2010
  3. Rajika Somasiri

    String concatination

    Rajika Somasiri, Feb 9, 2004, in forum: ASP .Net Web Controls
    Replies:
    1
    Views:
    131
    Tom Kiefer
    Feb 9, 2004
  4. Rajika Somasiri

    String concatination

    Rajika Somasiri, Feb 9, 2004, in forum: ASP .Net Web Controls
    Replies:
    2
    Views:
    106
    Anusha Nanayakkara
    Feb 23, 2004
  5. Crystal
    Replies:
    3
    Views:
    118
    Crystal
    Jul 9, 2003
Loading...

Share This Page