我想知道是否可以“嵌套”可变参数宏调用。我只关心GCC和Clang。我的宏定义如下所示:
/**
* @brief Invoke an instance method.
*/
#define $(obj, method, ...) \
({ \
typeof(obj) _obj = obj; \
_obj->interface->method(_obj, ## __VA_ARGS__); \
})
我用它在我的OO框架(https://github.com/jdolan/objectively)中方便地调用“实例方法”:
$(array, addObject, obj);
工作老板。不幸的是,我还没有找到一种允许嵌套这些调用的方法,这在某些情况下非常有用; e.g:
/**
* @see MutableSetInterface::addObjectsFromArray(MutableSet *, const Array *)
*/
static void addObjectsFromArray(MutableSet *self, const Array *array) {
if (array) {
for (size_t i = 0; i < array->count; i++) {
$(self, addObject, $(array, objectAtIndex, i));
}
}
}
上面嵌套的可变参数宏调用无法编译,因为永远不会扩展内部调用。是否有可能解决这个问题,或者我已经将预处理器滥用到了极限? :)
答案 0 :(得分:7)
这是嵌套预处理器宏的常见问题。预处理器扩展规则相当晦涩;相关的tl; dr是宏在层中扩展。解决方法是添加一个可以扩展参数的间接层:
#define MI(obj, method, ...) \
({ \
typeof(obj) _obj = obj; \
_obj->interface->method(_obj, ## __VA_ARGS__); \
})
#define M(obj, method, ...) MI(obj, method, __VA_ARGS__)
// This will now expand properly.
M(self, addObject, M(array, objectAtIndex, M(foo, bar, i)))
附注:请注意$
不是C的基本源字符集的一部分;使用它可能不便携。