如何实现EXCLUDE

以下代码在GCC中按预期工作,但不在MSVC中。

#define _EXCLUDE_FIRST_ARG_(first, ...) __VA_ARGS__
#define EXCLUDE_FIRST_ARG(...) _EXCLUDE_FIRST_ARG_(__VA_ARGS__)

例:

EXCLUDE_FIRST_ARG(a, b, c, d, e)

将在GCC中进行评估(也在CLANG中进行检查)

b, c, d, e

但是,当我用这个例子使用MSVC时,结果是空的。

而当我检查first论据_EXCLUDE_FIRST_ARG_ ,我发现,参数a, b, c, d, e都绑定到first参数,并留下...什么也没有。

这是因为MSVC预处理器缺少参数预扫描功能还是MSVC违反了一些c ++标准?

我怎样在使用MSVC时实现这个EXCLUDE_FIRST_ARG功能?


这是因为MSVC预处理器缺少参数预扫描功能还是MSVC违反了一些c ++标准?

下面就是它如何运行的最佳方式,因为我已经可以将它与Microsoft整合在一起。

1.宏定义:

#define _EXCLUDE_FIRST_ARG_(first, ...) __VA_ARGS__
#define EXCLUDE_FIRST_ARG(...) _EXCLUDE_FIRST_ARG_(__VA_ARGS__)

...显然会导致宏定义。

2.调用

EXCLUDE_FIRST_ARG(a, b, c, d, e)

MS的预处理器可以识别类似函数的宏EXCLUDE_FIRST_ARG已定义,因此可用于扩展:

2A。 参数识别

宏的形式参数定义... ; 它的参数a, b, c, d, e 。 这是一个没有命名参数的可变参数,所以所有参数绑定到可变参数。

2B。 参数替换

EXCLUDE_FIRST_ARG的替换列表中提及__VA_ARGS__ 。 它没有被串化或参与粘贴。 这使得它有资格进行参数替换。 在替换参数之前,表达式:

a, b, c, d, e

...由预处理器评估。 没有关于这些的特别之处(没有类似于函数的宏调用已经完成;并且没有任何参数是类对象宏),所以评估是相同的; 也就是说,评估的参数是:

a, b, c, d, e

通过参数替换规则,替换替换列表中的参数“名称”。 一旦发生这种情况,我们有这样的:

_EXCLUDE_FIRST_ARG_(a, b, c, d, e)

到目前为止,所有其他主要的预处理器都做同样的事情。 但是MS的预处理器在扩展__VA_ARGS__时表现出特殊的行为; 具体而言,其特点是整个替换只是一个令牌。 您可能会在扩展中看到逗号; 我也是; 但对于MS来说,它仍然只是一个令牌。

2 [在b和c之间]。 字符串化和粘贴,没有特别的顺序

这只是此帐户中的语义占位符。 这里是这些操作发生的地方,但由于我们在这种情况下没有发生任何事情。

2C。 重新扫描并进一步更换

在这一步,由此产生的替换列表本身:

_EXCLUDE_FIRST_ARG_(a, b, c, d, e)

...重新扫描以获取更多宏。 在此重新扫描期间,预处理器注意到用“参数” a, b, c, d, e (对其他主要预处理器,这是五个参数)调用类似对象的宏_EXCLUDE_FIRST_ARG_

2c.a. 参数识别

_EXCLUDE_FIRST_ARG_有一个命名参数first ,和变参。 注意:从技术上讲,必须在预C ++ 20预处理器中至少使用2个参数来调用它; 许多主要的预处理器(包括MS)接受少一个。

对于MS的预处理器,这是用一个参数调用的: a, b, c, d, e ,它first与参数相关联。 可变参数...是空的。

对于大多数其他主要的预处理器,这被称为五个参数。 first是与a ; ...b, c, d, e

2c.b. 参数替换

对于MS的预处理器,在替换列表中没有提到first ,所以没有任何关于相关的参数。 __VA_ARGS__ (未被__VA_ARGS__化/粘贴)不符合MS的逗号省略功能,因此空的可变参数会导致__VA_ARGS____VA_ARGS__替换。

对于大多数其他主要预处理程序,还是有不提first替换列表中,所以什么也没发生,以a__VA_ARGS__ (未被__VA_ARGS__化/粘贴)被提及,所以b, c, d, e被评估,导致b, c, d, e ; 该结果取代__VA_ARGS__

2c.c. 重新扫描并进一步更换

对于MS的预处理器,这里没有什么有趣的。 自完成后,地标将被删除。

对于其他预处理器, b, c, d, e再次被重新扫描,导致相同的结果。

我怎样在使用MSVC时实现这个EXCLUDE_FIRST_ARG功能?

在这种情况下,您可以使用助手将参数列表从宏中分离出来:

#define _EXCLUDE_FIRST_ARG_(first, ...) __VA_ARGS__
#define CALL(A,B) A B
#define EXCLUDE_FIRST_ARG(...) CALL(_EXCLUDE_FIRST_ARG_,(__VA_ARGS__))

EXCLUDE_FIRST_ARG(a, b, c, d, e)

粗略地说, EXCLUDE_FIRST_ARG在这个方法的阶段扩展为CALL(_EXCLUDE_FIRST_ARG_,(a, b, c, d, e)) 。 在重新扫描期间,在每次完全评估后,调用CALL (在此期间扩展为_EXCLUDE_FIRST_ARG_(a, b, c, d, e) 。 然后在CALL的重新扫描期间,参数列表再次看起来像多个标记。

链接地址: http://www.djcxy.com/p/72533.html

上一篇: How to implement EXCLUDE

下一篇: Collision of nested typenames in MSVC