gpt4 book ai didi

c++ - 计数 __VA_ARGS__ MSVC 给出意想不到的结果

转载 作者:太空宇宙 更新时间:2023-11-04 12:55:21 25 4
gpt4 key购买 nike

我正在尝试计算调用正确宏的参数数量。连接和参数数量似乎给出了预期的结果,但由于某些原因在 MSVC 上参数数量不起作用。我尝试了已知的修复程序,例如 EXPAND(x) x 和 EXPAND(...) __VA_ARGS__CALL(x,y) x y 但没有任何效果。我还硬编码了一个我知道有效的数字,编译后给出了正确的结果,因此我将问题缩小到计数宏。

编译后 VS 警告没有足够的参数,因为它调用了不正确的 _#_DERIVED(...) MACRO。

#define CONCAT_DETAIL(l, r) l##r
#define CONCAT(l, r) CONCAT_DETAIL(l, r)
#define _COUNT_N(_0, _1, _2, _3, _4, _5, _6, _7, _8, _9, _10, N, ...) N
#define _COUNT(...) _COUNT_N("ignore", ## __VA_ARGS__, _10, _9, _8, _7, _6, _5, _4, _3, _2, _1, _0)
#define _EXPAND(...) __VA_ARGS__
#define CLASS_BODY(...) CONCAT(_EXPAND(_COUNT(__VA_ARGS__)),_DERIVED)(__VA_ARGS__)

示例用法

CLASS_BODY(Renderer)
CLASS_BODY(Object, XMLParser)

宏编译后的预期结果

_0_DERIVED()
_1_DERIVED(arg1)
_2_DERIVED(arg1, arg2)
.
.
.

最佳答案

MSalters 是对的;带有单下划线的标识符是保留的。如果在实现中包含任何内容时您的宏处于事件状态,它可能会在您最不期望的时候发生冲突。

After compiling VS warns about ...

根据这段引述,我怀疑您是通过尝试编译宏来调试宏。更好的方法是只使用预处理器。在 Microsoft 中,您可以通过在开发控制台的命令行中运行 cl/EP foo.h 来执行此操作(或者在为您的特定实现运行 VCVARSALL 之后)。

现在是宏:

#define _COUNT_N(_0, _1, _2, _3, _4, _5, _6, _7, _8, _9, _10, N, ...) N
#define _COUNT(...) _COUNT_N("ignore", ## __VA_ARGS__, _10, _9, _8, _7, _6, _5, _4, _3, _2, _1, _0)
#define _EXPAND(...) __VA_ARGS__

_COUNT 需要展开一步,否则没用。这样更好:

#define COUNT_N(_0, _1, _2, _3, _4, _5, _6, _7, _8, _9, _10, N, ...) N
#define COUNT(...) EXPAND(COUNT_N( , __VA_ARGS__, _10, _9, _8, _7, _6, _5, _4, _3, _2, _1, _0))
#define EXPAND(...) __VA_ARGS__

现在:

COUNT() COUNT(a) COUNT(a,b)

...扩展为:

_1 _1 _2

技术上是正确的。 COUNT() 有一个参数(它是空的)。这在 Microsoft 中不返回 _0 的原因是因为扩展步骤......这正是允许 COUNT 宏首先工作的原因。如果您希望 COUNT() 返回 0,您需要添加另一层间接寻址使用CALL(因为参数列表需要展开一次以触发逗号省略):

#define COUNT_N(_0, _1, _2, _3, _4, _5, _6, _7, _8, _9, _10, N, ...) N
#define COUNT_M(...) EXPAND(COUNT_N( __VA_ARGS__, _10, _9, _8, _7, _6, _5, _4, _3, _2, _1, _0))
#define COUNT(...) CALL(COUNT_M,(, __VA_ARGS__))
#define CALL(X,Y) X Y
#define EXPAND(...) __VA_ARGS__

...现在 COUNT() 返回 _0;请注意,这是 Microsoft 特有的。

把它放在一起

#define CONCAT_DETAIL(l, r) l##r
#define CONCAT(l, r) CONCAT_DETAIL(l, r)
#define COUNT_N(_0, _1, _2, _3, _4, _5, _6, _7, _8, _9, _10, N, ...) N
#define COUNT_M(...) EXPAND(COUNT_N( __VA_ARGS__, _10, _9, _8, _7, _6, _5, _4, _3, _2, _1, _0))
#define COUNT(...) CALL(COUNT_M,(, __VA_ARGS__))
#define CALL(X,Y) X Y
#define EXPAND(...) __VA_ARGS__
#define CLASS_BODY(...) CONCAT(EXPAND(COUNT(__VA_ARGS__)),_DERIVED)(__VA_ARGS__)

CLASS_BODY()
CLASS_BODY(arg1)
CLASS_BODY(arg1,arg2)

...扩展为:

_0_DERIVED()
_1_DERIVED(arg1)
_2_DERIVED(arg1,arg2)

当然,您现在只是生成以 _ 开头的标识符。

关于c++ - 计数 __VA_ARGS__ MSVC 给出意想不到的结果,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/46920401/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com