为什么字符串连接宏不适用于这种"+"情况?
Why string concat macro doesn't work for this "+" case?
短问题:
是否允许为字符串连接宏##
连接特殊符号,如+
, -
?例如,
#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
通过阅读gcc的手册,我发现应该可以concat,但是为什么两个编译器都发出错误?
可以粘贴标点符号形成其他标点符号,例如
#define PASTE(a,b) a##b
int main()
{
int i = 0;
i PASTE(+,+);
// i == 1 now
}
##
运算符用于从其他预处理令牌生成有效的预处理令牌。粘贴的结果必须是有效的预处理令牌。所以这是无效的:
PASTE(i,++)
,因为i++
不是预处理令牌;它是两个相邻的令牌i
和++
。
可能的标记列表是(N3797):
- 头名称 <
- 标识符/gh>
- pp-number
- 字符文字量
- user-defined-character-literal
- 字符串
- user-defined-string-literal
- preprocessing-op-or-punc
- 每个非空白字符,不能是上述 之一
注:在预处理阶段,关键字不存在;但是在预处理之后,任何应该是关键字的标识符都被(语义上)转换为关键字。因此,您可以通过粘贴较短的单词来构建关键字。
在代码中,operator+
是两个令牌:operator
和+
。所以你不建立它与##
;你只需要做一个,然后做另一个。
#define OP(punc) operator punc
相关文章:
- FLTK 2.0构建和演示,适用于VS2019的2011年左右的代码库
- C++17 - 使用自定义分配器的节点提取/重新插入 - 适用于 clang++/libc++,但不适用于 libstd
- "string.h"在构建适用于iOS的qt应用程序中找不到消息
- 适用于 WebView2 旧版本的示例应用程序
- 在 NVIDIA GEFORCE GTX 1050 上下载适用于 Windows 10 的 openCL 1.2
- __attribute__(优化(0))) 是否适用于"recursively"?
- 为什么 std::erase(std::erase_if) 不是适用于<algorithm>任何容器的模板?
- 使用一个参数的模板函数时出错(适用于 2)
- 使用 适用于 Android 和 iOS 的 tf-lite C++ API
- 为什么这适用于 G++ 而不是 CLANG?
- 适用于 macOS 的 Xcode 应用程序。这就是我设置从USB麦克风输入获取音频的方式。一年前工作,现在没有了。为什么
- 适用于 Linux 的 c++ 上的代理脚本
- 为什么我的 SFINAE 表达式不再适用于 GCC 8.2?
- 使输出流式处理运算符适用于 boost::variant<std::vector<int>、int、double 的正确方法是什么>
- 有没有适用于Windows.lib文件的GNU二进制文件描述符(BFD)
- 模板函数仅适用于VS
- 如何在cmake中包含适用于g++或viceversa的库
- 适用于win32、linux、mac的POSIX C包装器
- WinDBG适用于从Visual Studio 2015保存的转储,但不适用于任务管理器。显示异常代码"not found"
- 从uint8_t到NPY_UINT16 PyArray_SimpleNewFromData.适用于Linux,但不适用于