我正在尝试计算调用正确宏的参数数量。连接和参数的数量似乎给出了预期的结果,但由于某种原因,在MSVC上,参数的数量不起作用。我尝试了EXPAND(x) x and EXPAND(...) __VA_ARGS__
和CALL(x,y) x y
等已知修复,但没有任何效果。我还硬编码了一个我知道可以工作的数字,在编译后它给出了正确的结果,所以我把问题缩小到了计数MACRO。
编译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)
MACRO编译后的期望结果
_0_DERIVED()
_1_DERIVED(arg1)
_2_DERIVED(arg1, arg2)
.
.
.
答案 0 :(得分:0)
MSalters是对的;具有单个下划线的标识符是保留的。如果您的宏在实现中包含任何内容时处于活动状态,则可能会在您最不期望的时候发生冲突。
编译后VS警告...
我怀疑基于这个引用你是通过尝试编译它们来调试你的宏。更好的方法是仅使用预处理器。在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
;请注意这是微软特有的。
#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)
当然,您现在只是生成以_
开头的标识符。