__VA_ARGS__ 使用 MSVC 扩展

__VA_ARGS__ expansion using MSVC

我发现了一个显示如何根据参数数量重载宏的问题: Overloading Macro on Number of Arguments

但正如他们所说,它无法使用 MSVC,因为 MSVC 将 __VA_ARGS__ 扩展为单个标记而不是参数列表 (arg1, arg2, arg3)。

他们指出了另一个问题,其中给出了解决方法:MSVC doesn't expand __VA_ARGS__ correctly 但完全没有解释,所以我不能适应我自己的情况,因为我看不懂。

能否解释一下此解决方法的工作原理?

有问题的解决方法是:

#define EXPAND( x ) x
#define F(x, ...) X = x and VA_ARGS = __VA_ARGS__
#define G(...) EXPAND( F(__VA_ARGS__) )

这个想法是给定一个现有的可变参数宏 F():

#define F(x, ...) X = x and VA_ARGS = __VA_ARGS__

而不是编写您想要的可变参数包装器宏,在这种情况下,...

#define G(...) F(__VA_ARGS__)

...您使用附加的 EXPAND() 宏编写 G()F() 的实际定义不是重点,特别是对于这个例子来说,宏展开不产生有效的 C 代码并不重要。其目的是演示预处理器关于宏参数的行为。具体来说,它表明尽管 MSVC 将 __VA_ARGS__ 扩展为可变参数宏中的单个标记,但可以通过强制双重扩展来解决这个问题。

例如,使用变通方法定义,预处理器首先展开...

G(1, 2, 3)

...到...

EXPAND( F(1, 2, 3) )

... 其中 1, 2, 3 被视为单个标记。但是,当预处理器重新扫描其他替换时,该标记化不再重要:它将 123 视为宏 F() 的单独参数,并将其扩展为希望生成宏 EXPAND() 的参数,它只是将其替换为自身。

如果您认为这按预期工作很奇怪,但没有 EXPAND() 的版本不起作用(在 MSVC 中),那么您是对的。