【发布时间】:2019-07-21 20:19:54
【问题描述】:
我知道,在扩展类似函数的预处理器宏时,顶级替换列表中的 # 和 ## 标记基本上在参数上的任何宏扩展“之前”起作用。例如,给定
#define CONCAT_NO_EXPAND(x,y,z) x ## y ## z
#define EXPAND_AND_CONCAT(x,y,z) CONCAT_NO_EXPAND(x,y,z)
#define A X
#define B Y
#define C Z
那么CONCAT_NO_EXPAND(A,B,C)是pp-token ABC,EXPAND_AND_CONCAT(A,B,C)是pp-token XYZ。
但是如果我想定义一个在粘贴之前只扩展它的一些参数的宏怎么办?例如,我想要一个只允许扩展三个参数中间的宏,然后将它与一个完全未扩展的前缀和一个完全未扩展的后缀一起粘贴,即使前缀或后缀是类对象宏的标识符。也就是说,如果我们有
#define MAGIC(x,y,z) /* What here? */
#define A X
#define B Y
#define C Z
那么MAGIC(A,B,C) 就是AYC。
一个简单的尝试
#define EXPAND(x) x
#define MAGIC(x,y,z) x ## EXPAND(y) ## z
导致错误“粘贴“)”和“C”没有给出有效的预处理令牌”。这是有道理的(我假设它也会产生不需要的令牌AEXPAND)。
有没有什么方法可以只使用标准的、可移植的预处理器规则来获得这种结果? (没有额外的代码生成或修改工具。)
如果不是,也许是一种适用于大多数常见实现的方法?在这里 Boost.PP 将是公平的游戏,即使它涉及一些特定于编译器的技巧或解决方法。
如果有什么不同的话,我最感兴趣的是 C++11 和 C++17 中定义的预处理器步骤。
【问题讨论】:
-
"然后
MAGIC(A,B,C)是AYC。" 好吧,让我们同意要求 magic 至少是 题外话. -
@πάνταῥεῖ 不,我不同意,这种使用“魔法”(这个词)来表示解决方案的方式是一个好方法。这样我就经常在工作中使用魔法。
标签: c++ c-preprocessor