c++ - 为什么字符串连接宏不适用于这个 "+"案例?

标签 c++ gcc macros clang

小问题:

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

#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我发现应该可以进行连接,但为什么两个编译器都会发出错误?

最佳答案

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

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

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

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

PASTE(i,++)

因为 i++ 不是预处理标记;它是两个相邻的标记 i++

可能的标记列表是 (N3797):

  • 标题名称
  • 标识符
  • 页数
  • 字 rune 字
  • 用户定义的字 rune 字
  • 字符串文字
  • 用户定义的字符串文字
  • 预处理-op-or-punc
  • 每个不能是上述之一的非空白字符

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

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

#define OP(punc) operator punc

关于c++ - 为什么字符串连接宏不适用于这个 "+"案例?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/25072193/

相关文章:

c++ - 具有默认参数值的函数中的默认对象值

C++ 函数宏的开始和结束

java - 您将使用什么工具来完成重新格式化 java 代码的任务?

c++ - GCC avx2intrin.h(版本 X-9.2)中缺少 _mm_broadcastsd_pd

c++ - 使用 define 作为 define C(++) 的参数

c# - 将二维数组 double[][] 传递给 c# windows 应用程序

c++ - 为什么我的异常没有被捕获

c++ - Visual Studio 跨平台生成文件项目,找不到命令

c++ - 如何使应用程序符号对库可见?

c - 如何在保持动态加载的同时静态链接libc?