宏中的波浪号 (~) 是啥意思?

Posted

技术标签:

【中文标题】宏中的波浪号 (~) 是啥意思?【英文标题】:What does the tilde (~) in macros mean?宏中的波浪号 (~) 是什么意思? 【发布时间】:2011-09-22 15:43:21 【问题描述】:

在this site 上看到,代码显示使用括号中的波浪号的宏调用:

HAS_COMMA(_TRIGGER_PARENTHESIS_ __VA_ARGS__ (~))
//                                          ^^^

这是什么意思/做什么?我怀疑这只是一个空洞的论点,但我不确定。它是否可能特定于 C(99),就像 __VA_ARGS__ 特定于 C99 并且存在于 C++ 中?

【问题讨论】:

~ 是按位补码,您可能知道。对我来说似乎只是一个占位符。我不认为它有什么特殊含义。 【参考方案1】:

在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++ 实现需要支持的基本字符集的一部分。像被忽略的标识符可能会受到宏扩展的影响,从而导致意外结果。

因此,波浪号只是一个占位符,因为需要一个参数,但没有一个参数是必需的。由于任何用户定义的标识符都可以扩展,因此您需要使用其他东西。

事实证明,与+- 相比,~ 几乎没有被使用(二元否定并不经常被调用),因此几乎没有混淆的可能性。一旦你确定了这一点,持续使用它会给波浪号赋予的含义;就像使用operator&lt;&lt;operator&gt;&gt; 处理流数据一样已经成为C++ 习惯用法。

【讨论】:

我的 +1,这是一个非常好的发现!我找不到它的任何标准参考,并且正在努力彻底理解它。您的回答很好地解决了问题。 考虑到 TINY_size 的扩展中没有出现参数(以及因此宏扩展的参数),宏扩展究竟如何导致意外结果? @Random832:宏扩展对我来说一直有点模糊,但我认为例如#define unused a, b,现在TINY_size 将使用4 个参数而不是3 个参数调用,因此代码会被拒绝。【参考方案2】:

~ 什么都不做。这些括号内的几乎所有其他内容都可以使用。

这个技巧的关键是在_TRIGGER_PARENTHESIS_ __VA_ARGS__ (~)的扩展中测试_TRIGGER_PARENTHESIS_是否在(~)旁边。无论哪种方式,HAS_COMMA(...) 都将其参数扩展为 01

【讨论】:

我想知道这将如何与宏本身的参数一起发挥作用.._TRIGGER_PARENTHESIS_ MYMACRO (~). 他为什么用(~)而不是(+)或者别的什么? @Johannes:Boost.Preprocessor 简介页面上提供了一个推理,我在下面引用了。目标是使用有效但稀有的预处理器令牌。【参考方案3】:

要测试的参数放在宏和它的括号之间,宏只有在参数为空时才会触发:

_TRIGGER_PARENTHESIS_ __VA_ARGS__ (~)

注意:实际上您发布的链接说明了这一点。我将在标准中检查对此的引用。

【讨论】:

请注意:是的,在发布问题后重读了几次后,它来到了我这里......这不是我第一次提出问题,几分钟后解决方案来了记住...... :(另外,你的第一句话似乎与问题没有直接关系。 @Xeo:抱歉,恐怕我对上下文的理解不够透彻,无法发布详细的答案,关于为什么只有~ 存在松散的结局,我一直在破坏标准很长时间没有成功。太好了,由@Matthieu M 找到。不过,我可以安然入睡! 感谢您的努力。 :)

以上是关于宏中的波浪号 (~) 是啥意思?的主要内容,如果未能解决你的问题,请参考以下文章

帮看下这句css中的波浪号是啥意思

purrr::map 中的第一个波浪号是啥意思

CSS中的符号波浪号(〜)是啥意思[重复]

创建 Java 泛型类时,尖括号中的波浪号是啥意思?

Rust 声明性宏中的 @ 符号是啥意思?

Rust 宏中的 tt 元变量类型是啥意思?