【问题标题】:Why string concat macro doesn't work for this "+" case?为什么字符串 concat 宏不适用于这种“+”情况?
【发布时间】:2014-08-01 02:57:30
【问题描述】:

小问题:

字符串拼接宏##是否允许拼接+-等特殊符号?例如,

#define OP(var) operator##var

OP(+) 是否会扩展为 operator+

确切的问题:

#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
}

对于strOpMap2,使用clang++ -c -std=c++11,它会报告:

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

在使用g++ -c -std=c++11 时,它给出:

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

通过阅读the manual by gcc,我发现应该可以连接,但为什么两个编译器都会发出错误?

【问题讨论】:

  • operator +两个 令牌,而不是一个。
  • @DavidRodríguez-dribeas 所以 concat 宏结果只会是一个令牌?为什么operator + 是两个令牌? operator+ 应该被识别为一个操作符函数,对吧?
  • operator 是一个关键字。要得到你想要的,#define OP(var) operator var
  • @MattMcNabb 谢谢,这行得通!

标签: c++ gcc macros clang


【解决方案1】:

您可以粘贴标点符号以形成其他标点符号,例如

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

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

## 运算符用于从其他预处理令牌生成有效的预处理令牌。粘贴的结果必须是有效的预处理令牌。所以这是无效的:

PASTE(i,++)

因为i++ 不是预处理令牌;这是两个相邻的令牌i++

可能的令牌列表是 (N3797):

  • 标题名称
  • 标识符
  • pp 号
  • 字面量
  • 用户定义的字符文字
  • 字符串字面量
  • 用户定义的字符串文字
  • 预处理操作或穿孔
  • 不能是上述之一的每个非空白字符

注意:在预处理阶段,keyword是不存在的;但是在预处理之后,任何应该是关键字的标识符都会(语义上)转换为关键字。因此,您可以通过粘贴较短的单词来构建关键字。

在您的代码中,operator+ 是两个标记:operator+。所以你不要用## 构建它;你只做一个然后另一个。

#define OP(punc) operator punc

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2015-10-26
    • 2018-07-03
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2022-06-10
    • 2012-05-12
    相关资源
    最近更新 更多