是否可以使用单个typedef定义不带参数并返回一个块的块?

时间:2019-02-09 18:14:21

标签: objective-c

类似/跟进此问题: Syntax to define a Block that takes a Block and returns a Block in Objective-C

我知道这不是我想要做的,但是我想了解为什么我不能使用单个typedef来定义:

typedef void (^XYZSimpleBlock)(void);
typedef XYZSimpleBlock (^ComplexBlock)(void);

为什么上述方法有效,但这无效?

typedef void(^)(void) (^ComplexBlock)(void);

如果我得到类似的答案,我发现我可以像编译器一样尝试解析它,但是我是一个不好的编译器。

遵循C的左右规则,第一个标识符不是ComplexBlock吗?

typedef void(^)(void) (^ComplexBlock)(void);
// parser reads left right and finds ComplexBlock first

然后它将右移并找到声明的结尾,然后向左移直到找到插入符,然后向右解释参数列表。

那把我们带到了

 typedef void(^)(void) (^ComplexBlock)(void);
//       | unhandled   |compiled/interpreted| 

这时发生了什么情况,它无法将void(^)(void)读取为返回类型?

让我感到困惑的是,使用typedef基本上只是一个#define,所以它不应该与上面基本相同吗?

typedef void (^XYZSimpleBlock)(void);
same as:
void(^)(void)    
so:
typedef XYZSimpleBlock (^ComplexBlock)(void);
should be the same as:
typedef void(^)(void) (^ComplexBlock)(void);

我在这里想念东西...

1 个答案:

答案 0 :(得分:3)

正确的语法是:

typedef void (^(^ComplexBlock)(void))(void);

像这样构造复杂类型的声明时,它可以帮助从更简单的类型开始,并将“表达式”替换为标识符。

例如,声明一个不带任何参数并返回void的函数:

void a_func(void);

现在,我们要声明一个函数指针a_func_ptr,它是指向相同类型函数的指针。我们希望表达式*a_func_ptra_func具有相同的类型,因此我们将该表达式放在括号中,并放到上面并得到:

void (*a_func_ptr)(void);

如果要使用块指针而不是函数指针,请使用^代替*

void (^a_block_ref)(void);

(人们发现块语法令人沮丧的一个原因是,人们从未真正写过表达式^a_block_ref来“解引用”一个块变量,因此这种跨越是不明显的。)

采用上述方法并在其中typedef(而不是变量声明)中,您将获得:

typedef void (^XYZSimpleBlock)(void);

但是,暂时让我们回到函数指针a_func_ptr。假设您想声明一个返回函数指针的函数func_returns_func。您将函数调用表达式放在a_func_ptr所在的位置。也就是说,您将func_returns_func()放入:

void (*func_returns_func())(void);

现在,在声明函数时,您无需使用void而不使用参数,因此您可以这样做:

void (*func_returns_func(void))(void);

请注意,您不会在标识符左侧收集或隔离返回类型。它围绕标识符。

现在,将*更改为^,以获得返回块引用而不是函数指针的函数:

void (^func_returns_block(void))(void);

我们创建一个指向返回块引用的函数的指针。将(*ptr_to_func_returns_block)放入func_returns_block并获得:

void (^(*ptr_to_func_returns_block)(void))(void);

再次,将*替换为^,以获得对块的引用,该块返回一个块引用:

void (^(^block_returns_block)(void))(void);

我们在那里。只需更改名称,即可获得:

void (^(^ComplexBlock)(void))(void);