宏中的波形符 (~) 是什么意思?

发布于 2024-11-17 04:22:08 字数 361 浏览 1 评论 0原文

此网站上看到的代码显示了宏调用在括号中使用波形符:

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

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

Seen on this site, the code shows macro invocations using a tilde in parentheses:

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

What does it mean / do? I suspect it to just be an empty argument, but I'm not sure. Is it maybe specific to C(99) like the __VA_ARGS__ is specific to C99 and existent in C++?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

楠木可依 2024-11-24 04:22:08

在Boost.Preprocessor的介绍页面,在A.4.1.1 Horizo​​ntal Repetition中给出了一个例子,

#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_sizeTINY_size)。第一个参数指定重复调用的次数,第三个参数可以是任意数据;它原封不动地传递给正在调用的宏。 在本例中,TINY_size 不使用该数据,因此传递 ~ 的选择是任意的。 [5]

(强调我的)

并且有注释:

[5] ~ 并不是一个完全任意的选择。 @$ 可能都是不错的选择,只是从技术上讲它们不属于 C++ 实现需要支持的基本字符集。像忽略这样的标识符可能会受到宏扩展的影响,从而导致意外的结果。

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

事实证明,与 +- 相比,~ 几乎没有被使用(二进制否定并不经常被调用),所以有混淆的可能性很小。一旦您确定了这一点,持续使用它就会给波形符带来含义;就像使用 operator<<operator>> 来流数据一样,已经成为 C++ 的习惯用法。

On the introduction page of Boost.Preprocessor, an example is given in A.4.1.1 Horizontal Repetition

#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

An explanation is provided below:

The code generation process is kicked off by calling BOOST_PP_REPEAT, a higher-order macro that repeatedly invokes the macro named by its second argument (TINY_size). The first argument specifies the number of repeated invocations, and the third one can be any data; it is passed on unchanged to the macro being invoked. In this case, TINY_size doesn't use that data, so the choice to pass ~ was arbitrary. [5]

(emphasis mine)

And there is the note:

[5] ~ is not an entirely arbitrary choice. Both @ and $ might have been good choices, except that they are technically not part of the basic character set that C++ implementations are required to support. An identifier like ignored might be subject to macro expansion, leading to unexpected results.

The tilde, therefore, is simply a place holder because an argument is required, but none is necessary. Since any user-defined identifier wannabe could be expanded, you need to use something else.

It turns out that ~ is pretty much unused (binary negation is not that often called) in comparison to + or - for example, so there is little chance of confusion. Once you've settled on this, using it consistently gives it a new meaning to the tilde; like using operator<< and operator>> for streaming data has become a C++ idiom.

帅气尐潴 2024-11-24 04:22:08

~ 不执行任何操作。括号内的几乎所有其他内容都具有相同的作用。

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

The ~ does nothing. Almost any other content inside those parentheses would work the same.

The lynchpin of this trick is to test whether _TRIGGER_PARENTHESIS_ is next to (~) in the expansion of _TRIGGER_PARENTHESIS_ __VA_ARGS__ (~). Either way, HAS_COMMA(...) expands its arguments to either 0 or 1.

未央 2024-11-24 04:22:08

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

_TRIGGER_PARENTHESIS_ __VA_ARGS__ (~)

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

The arguments to be tested is placed between the macro and its parenthesis, the macro only triggers if the arguments are empty:

_TRIGGER_PARENTHESIS_ __VA_ARGS__ (~)

NOTE: Actually the very link you posted states it. I will check for a reference to this in the standard.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文