简体   繁体   中英

Why string concat macro doesn't work for this “+” case?

Short question:

Is it permitted to concat special signs such as + , - for the string concatenation macro ## ? For example,

#define OP(var) operator##var

will OP(+) be expanded to operator+ ?

Exact problem:

#include "z3++.h"
#include <unordered_map>

namespace z3 {
z3::expr operator+(z3::expr const &, z3::expr const &);
}

typedef z3::expr (*MyOperatorTy)(z3::expr const &, z3::expr const &);

#define STR(var) #var
#define z3Op(var) static_cast<MyOperatorTy>(&z3::operator##var)
#define StrOpPair(var) \
  { STR(var), z3Op(var) }

void test() {
  std::unordered_map<std::string, MyOperatorTy> strOpMap1{
      {"+", static_cast<MyOperatorTy>(&z3::operator+)}};  // fine
  std::unordered_map<std::string, MyOperatorTy> strOpMap2{StrOpPair(+)}; // error
}

For strOpMap2 , using clang++ -c -std=c++11 , it reports:

error: pasting formed 'operator+', an invalid preprocessing token

while using g++ -c -std=c++11 , it gives:

error: pasting "operator" and "+" does not give a valid preprocessing token

By reading the manual by gcc I find it should be possible to concat, but why both compilers emit errors?

You can paste punctuation to form other punctuation, eg

#define PASTE(a,b) a##b

int main()
{
     int i = 0;
     i PASTE(+,+);
     // i == 1 now
}

The ## operator is for producing a valid preprocessing token from other preprocessing tokens. The result of pasting must be a valid preprocessing token. So this is not valid:

PASTE(i,++)

because i++ is not a preprocessing token; it's two adjacent tokens i and ++ .

The list of possible tokens is (N3797):

  • header-name
  • identifier
  • pp-number
  • character-literal
  • user-defined-character-literal
  • string-literal
  • user-defined-string-literal
  • preprocessing-op-or-punc
  • each non-white-space character that cannot be one of the above

Note: at the preprocessing stage, keyword does not exist; but after preprocessing, any identifiers which should be keyword are converted (semantically) into keywords. So you can build keywords by pasting shorter words.

In your code, operator+ is two tokens: operator and + . So you do not build it with ## ; you just do one then the other.

#define OP(punc) operator punc

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM