在这个网站上看到,代码显示了使用括号中的波浪号的宏调用:
HAS_COMMA(_TRIGGER_PARENTHESIS_ __VA_ARGS__ (~))
// ^^^
这是什么意思/做什么?我怀疑这只是一个空洞的论点,但我不确定。它是否可能特定于 C(99),就像__VA_ARGS__
特定于 C99 并且存在于 C++ 中一样?
在这个网站上看到,代码显示了使用括号中的波浪号的宏调用:
HAS_COMMA(_TRIGGER_PARENTHESIS_ __VA_ARGS__ (~))
// ^^^
这是什么意思/做什么?我怀疑这只是一个空洞的论点,但我不确定。它是否可能特定于 C(99),就像__VA_ARGS__
特定于 C99 并且存在于 C++ 中一样?
在Boost.Preprocessor的介绍页面,A.4.1.1 水平重复中给出了一个例子
#define TINY_print(z, n, data) data
#define TINY_size(z, n, unused) \
template <BOOST_PP_ENUM_PARAMS(n, class T)> \
struct tiny_size< \
BOOST_PP_ENUM_PARAMS(n,T) \
BOOST_PP_COMMA_IF(n) \
BOOST_PP_ENUM( \
BOOST_PP_SUB(TINY_MAX_SIZE,n), TINY_print, none) \
> \
: mpl::int_<n> {};
BOOST_PP_REPEAT(TINY_MAX_SIZE, TINY_size, ~) // Oh! a tilde!
#undef TINY_size
#undef TINY_print
解释如下:
代码生成过程通过调用 开始
BOOST_PP_REPEAT
,这是一个高阶宏,它重复调用由其第二个参数 (TINY_size
) 命名的宏。第一个参数指定重复调用的次数,第三个可以是任意数据;它被原封不动地传递给被调用的宏。在这种情况下,TINY_size
不使用该数据,因此通过的选择~
是任意的。[5]
(强调我的)
并且有注释:
[5]
~
不是一个完全武断的选择。两者都@
可能$
是不错的选择,只是它们在技术上不是 C++ 实现需要支持的基本字符集的一部分。像被忽略的标识符可能会受到宏扩展的影响,从而导致意外结果。
因此,波浪号只是一个占位符,因为需要一个参数,但没有一个参数是必需的。由于任何用户定义的标识符都可以扩展,因此您需要使用其他东西。
事实证明,与或~
相比,它几乎没有被使用(二元否定并不经常被称为),因此几乎没有混淆的可能性。一旦您确定了这一点,始终如一地使用它会给波浪号赋予新的含义;像使用和处理流数据一样已经成为 C++ 的习惯用法。+
-
operator<<
operator>>
~
什么都不做。这些括号内的几乎所有其他内容都可以正常工作。
这个技巧的关键是测试_TRIGGER_PARENTHESIS_
是否(~)
在_TRIGGER_PARENTHESIS_ __VA_ARGS__ (~)
. 无论哪种方式,HAS_COMMA(...)
都将其论点扩展为0
or 或1
。
要测试的参数放在宏及其括号之间,宏仅在参数为空时触发:
_TRIGGER_PARENTHESIS_ __VA_ARGS__ (~)
注意:实际上您发布的链接说明了它。我将在标准中检查对此的参考。