小问题:
是否允许为字符串连接宏##
连接特殊符号,例如+
、-
?例如,
#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/