【问题标题】:how to pass block as a macro's argument in objective-c?如何在objective-c中将块作为宏的参数传递?
【发布时间】:2013-10-01 06:02:45
【问题描述】:

在我的代码中,我有很多类似的代码:

if (block) block(....)

所以我想定义一个宏,比如

#define safetyCall(block, ...) if((block)) {block(##__VA_ARGS__)};

但我无法让它工作。有什么想法吗?

【问题讨论】:

  • 如果我调用safetyCall(method, 0, newErr); 编译器说:“粘贴形成'(0',一个无效的预处理令牌”和“预期的';'表达式后”

标签: objective-c-blocks


【解决方案1】:

您不需要 ##; 需要移动:

#define safetyCall(block, ...) if((block)) { block(__VA_ARGS__); }

【讨论】:

  • 顺便说一句,__VA_ARGS__##__VA_ARGS__ 之间有什么区别
  • @jAckOdE ## 标记用于“字符串化”它的参数(即将它们从 x 转换为 "x")。
  • @trojanfoe,不完全是。 ## 用于令牌粘贴。 # 是字符串化。这是原始错误所说的一部分。
  • @KenThomases 是的 - 是的。
  • @KenThomases:在这种情况下不完全是。 ##__VA_ARGS__ 之前使用时,是一个 GCC 扩展,如果 __VA_ARGS__ 为空,则删除前面的逗号: gcc.gnu.org/onlinedocs/gcc/Variadic-Macros.html 在这种情况下没有必要,因为 __VA_ARGS__ 是整个参数列表;但是对于block(something, __VA_ARGS__),如果可变参数为空,它将失败,在这种情况下,他需要block(something, ##__VA_ARGS__)
【解决方案2】:

如果您的块是内联的并且包含具有一系列逗号分隔字符串等的代码,这可能会遇到问题。

例子:

safetyCall(^void() {
  NSArray *foo = @[@"alice", "bob"];
};

编译器会报错“预期的']'或'.'”和“预期的标识符或'('”。

但是,如果您将内联块声明为宏之前的单独块,则不会产生错误。

例子:

void (^fooBlock)(void) = ^void() {
  NSArray *foo = @[@"alice", @"bob"];
}

safetyCall(fooBlock);

【讨论】:

  • 或者只是将块括在括号中
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2013-09-04
  • 2016-02-15
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-01-28
相关资源
最近更新 更多