【发布时间】:2018-07-04 05:14:05
【问题描述】:
用__VA_OPT__写递归宏合法吗?
GCC 和 Clang 似乎不会递归替换,但我不确定它是否是故意的(因为 __VA_OPT__ 支持是最近才出现的)。
C++ 规范(§19.3.1/3:
__VA_OPT__):否则,替换包括扩展的结果 content 作为当前类函数宏的替换列表 在重新扫描和进一步替换之前
上面突出显示的部分是否意味着不可能递归?
例如,添加可变参数宏参数列表:
#define RECURSE(mFIRST, ...) + mFIRST __VA_OPT__(RECURSE(__VA_ARGS__))
int main(int argc, char const* const argv[])
{
return 1 RECURSE(2, 3, 4);
// Expected result: "return 1 + 2 + 3 + 4;"
}
GCC 和 Clang 都在它们的后处理中生成 RECURSE。
// NOTE: Below is the output from g++ -E
int main(int argc, char const* const argv[])
{
return 1 + 2 RECURSE(3, 4);
}
注意:如果可能的话,可以相当容易地编写更复杂的可变参数宏,例如连接,因为您可以从 __VA_OPT__ 创建自定义 __VA_NO_OPT__,它允许您为 1 和 2+ 提供完全独立的代码参数。
【问题讨论】:
-
仅仅是因为它们总是会无限递归吗?因为
__VA_OPT__不再适用。 -
我猜这是因为:19.3.4/2:重新扫描并进一步更换。 “如果在替换列表的扫描过程中发现被替换的宏的名称(不包括源文件的其余预处理标记),则不会被替换”。
-
不太可能被修改。 C++ 非常努力地摆脱每次修订都使用宏的需要。由于各种原因,它不能,但不太可能添加递归。
__VA_OPT__是一个很小的便利功能。递归宏是一项巨大的变化。 -
@NicolBolas:AFAICT
__VA_OPT__是 c++2a 功能,而不是 c++17 功能,因此标签回滚。如果我被误导了,请道歉。
标签: c++ preprocessor c++20