可变宏:扩展粘贴的令牌 [英] Variadic macros: expansion of pasted tokens

查看:166
本文介绍了可变宏:扩展粘贴的令牌的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想知道是否可以嵌套可变宏调用。我只是真正关心GCC和Clang。我的宏定义如下所示:

  / ** 
* @brief调用实例方法。
* /
#define $(obj,method,...)\
({\
typeof(obj)_obj = obj; \
_obj-> interface->方法(_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));



code
$ b

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

解决方案

这是嵌套预处理器宏的常见问题。预处理器扩展规则相当神秘;相关的tl; dr是宏分层展开的。解决方法是添加一个可以扩展参数的间接层:

  #define MI(obj,method ,. ..)\ 
({\
typeof(obj)_obj = obj; \
_obj-> interface->方法(_obj,## __VA_ARGS__); \
})

#define M(obj,method,...)MI(obj,method,__VA_ARGS__)

//现在将正确扩展。
M(self,addObject,M(array,objectAtIndex,M(foo,bar,i)))

注意:注意 $ 不是C的基本源字符集的一部分;使用它可能不会便携。


I'm wondering if it's possible to "nest" variadic macro invocations. I'm only truly concerned with GCC and Clang. My macro definition looks like this:

/**
 * @brief Invoke an instance method.
 */
#define $(obj, method, ...) \
    ({ \
        typeof(obj) _obj = obj; \
        _obj->interface->method(_obj, ## __VA_ARGS__); \
    })

I use this to conveniently call "instance methods" in my OO framework (https://github.com/jdolan/objectively):

$(array, addObject, obj);

Works boss. Unfortunately, I haven't yet figured out a way to allow nesting of these calls, which would be very useful in some situations; 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));
        }
    }
}

The nested variadic macro invocation above fails to compile because the inner invocation is never expanded. Is it possible to fix this, or have I already abused the preprocessor to its limits? :)

解决方案

This is a common problem with nested preprocessor macros. Preprocessor expansion rules are fairly arcane; the relevant tl;dr is that macros are expanded in layers. The workaround is to add a layer of indirection in which the parameter can be expanded:

#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)))

Side note: be aware that $ is not part of C's basic source character set; using it will probably not be portable.

这篇关于可变宏:扩展粘贴的令牌的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆