c - 可变参数宏 : expansion of pasted tokens

标签 c gcc macros clang variadic-macros

我想知道是否可以“嵌套”可变宏调用。我只真正关心 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);

厂长。不幸的是,我还没有找到允许嵌套这些调用的方法,这在某些情况下非常有用;例如:

/**
 * @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));
        }
    }
}

上面的嵌套可变参数宏调用无法编译,因为内部调用从未展开。是否有可能解决这个问题,或者我是否已经将预处理器滥用到极限? :)

最佳答案

这是嵌套预处理器宏的常见问题。预处理器扩展规则相当神秘;相关的 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 的基本源字符集的一部分;使用它可能无法携带。

关于c - 可变参数宏 : expansion of pasted tokens,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/27514116/

相关文章:

c - C 中指针的表达

java - Scala 宏找不到 java.util.List、java.lang.Object

c - 为什么 printf(创建单位矩阵)不打印输出?

c - 我如何删除信号处理程序

char* str ="..."与 char str[] ="..."奇怪的行为

c++ - 为什么参数不是常量表达式?

c++ - 使用宏创建样板代码

c - 从文件中读取数据到结构体数组 (C)

c - 指向常量整数数组的指针

C- "Segmentation fault: 11"运行程序