user855
user855

Reputation: 19918

C++ preprocessor ## operator

What is wrong? I would like the xconcat line to work.

#define concat(a,b) a ## b
#define xconcat(a,b) concat(a,b)

int main() {
    xconcat(xconcat(boost::variant<,int), >) y;
    boost::variant<int> x;
    return 0;
}

g++ -E x.cpp

# 1 "x.cpp"
# 1 "<built-in>"
# 1 "<command-line>"
# 1 "x.cpp"



int main() {
x.cpp:5:1: error: pasting "<" and "int" does not give a valid preprocessing token
x.cpp:5:1: error: pasting "int" and ">" does not give a valid preprocessing token
    boost::variant<int > y;
    boost::variant<int> x;
    return 0;
}

Upvotes: 1

Views: 186

Answers (1)

Michael Burr
Michael Burr

Reputation: 340198

The token pasting operator technically can't be used to paste something that doesn't end up being a token. GCC enforces that restriction, while some other compilers don't (the ## operator just seems to perform basic concatenation of the strings which then gets tokenized later).

From C++11 16.3.3/3 "The ## operator":

If the result is not a valid preprocessing token, the behavior is undefined.

The same language is in pretty much every C and C++ standard going back to C90.

In your case you don't need to use token pasting since you're dealing with separate tokens anyway:

#define yyconcat(a,b) a b
#define yconcat(a,b) yyconcat(a,b)

int main() {
    yconcat(yconcat(boost::variant<,int), >) y;
    boost::variant<int> x;
    return 0;
}

g++ -E so-test.c

C:\so-test>g++ -E so-test.c
# 1 "so-test.c"
# 1 "<command-line>"
# 1 "so-test.c"



int main() {
    boost::variant< int > y;
    boost::variant<int> x;
    return 0;
}

Upvotes: 1

Related Questions