【问题标题】:__VA_ARGS__ expansion using MSVC__VA_ARGS__ 使用 MSVC 扩展
【发布时间】:2015-11-30 16:18:02
【问题描述】:

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

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

他们指出了另一个问题:MSVC doesn't expand __VA_ARGS__ correctly 但根本没有解释,所以我无法理解它,所以我无法适应我自己的情况。

您能否解释一下这种解决方法的工作原理?

【问题讨论】:

  • 我认为链接的帖子不正确。我认为正确的解决方案是G(...) F(EXPAND(__VA_ARGS__) )
  • @LPs,我也是这么想的,不过试试看。
  • @JohnBollinger 我太熟悉 Linux 了,无法使用 MSVC :)。说真的,我还没有 MSVC 来测试它。让 OP 试试吧
  • 不,在 Linux 上尝试您的版本。 Gcc 抛出错误。
  • 谢谢,但这仍然不能解释此解决方法背后的逻辑。

标签: c visual-c++ macros variadic-macros


【解决方案1】:

有问题的解决方法是这样的:

#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() 的单独参数,并根据需要扩展它以生成宏 @ 的参数987654336@,它只是将其替换为自身。

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

【讨论】:

  • 感谢您的帮助!我稍后会看看这个!
  • 它有效,谢谢。我现在也更明白了。使用另一个宏调用应该扩展参数的宏会导致编译器正确扩展参数。
  • 其实我的情况有点不同。我想根据参数的数量进行重载:1 arg -> 1 arg 的方法,2 args -> 2 args 的方法。但是:我也想要>2 args -> 2 args + va args 的方法,因为我的宏的两个重载可以在它们的强制参数之后有一个 arg 列表。这给我带来了一个问题,因为当我用> 2个参数调用我的方法时,第三个参数被用作方法名称,这是错误的。
  • 我能想到的解决方案是在返回实际宏名称的宏中硬编码最大数量的参数(即链接问题中的 GET_MACRO() )。这可以通过重定向到 2 个 args 直到 32 个 args 的重载来完成。但这似乎有点脏。您对如何更清楚地处理它有什么想法吗?虽然如果它不容易想到,不要浪费你的时间。谢谢。
  • 宏不能被重载,并且它们不能计算它们的参数,无论是否可变参数。您可以只使用两个宏来完成您所描述的操作,一个用于 1-arg 特殊情况,另一个用于 2 个或更多参数。后者的形式为MACRO2(arg1, ...),因为... 必须始终对应至少一个实际参数。
猜你喜欢
  • 2011-07-05
  • 2012-08-01
  • 2015-12-02
  • 2021-09-09
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-02-29
相关资源
最近更新 更多