在没有标识符的情况下如何读取复杂的C++类型声明?

How to read complicated C++ type declarations when there is no identifier?

本文关键字:复杂 读取 C++ 声明 类型 标识符 情况下 何读取      更新时间:2023-10-16

有众所周知的螺旋和左右规则等,用于读取复杂的C++类型,例如

int (*(*foo)(char *,double))[9][20];

Foo是一个指针(改变方向,移出括号(

到一个函数,将指针指向 char 和一个双精度,然后返回(再次更改方向(

指向的指针(再次用括号括起来,改变方向(

尺寸为 9,20 的 2D 阵列(到达右端,向左螺旋外侧(

整数。

但是,如果没有标识符,例如在定义函数参数的类型时,我如何处理这样的类型:

void foo(int *(*(* )(int(* )(int (* )(int))))())
^       ^        ^
identifiers omitted

如何以直观的方式识别最里面的元素? 顺便说一下,即使是 cdecl 工具在最后一个示例中也给出了语法错误,但它确实可以编译。

当然,编译器有一种定义明确的方法来解析像这样的乱码。它如何知道从哪里开始?

读取复杂类型的规则假定该类型已被解析(并且您知道"最内层"点在哪里(。从外到内解析工作的规则,与数学课上阅读复杂表达式相同。当你点击括号时,给它一个名字,然后回到它(除非它足够简单,可以自己处理(。免责声明:我使用文本编辑器来查找匹配的括号。 ;)

与此声明相关的另一个注意事项是,一旦类型是函数,参数列表中的混乱就是一个单独的解析。例如,在解析void (*)(big old mess)时,您有一个指向函数的指针。函数的签名需要很大的旧混乱,而不是理解您正在处理函数。

转到手头的示例:

void foo(int *(*(* )(int(* )(int (* )(int))))())

读完voidfoo,你打了括号,里面有一个复杂的混乱。给那个烂摊子起个名字。

void foo( A )

A在哪里int *(*(* )(int(* )(int (* )(int))))().所以你最外层的解析是一个返回void的一元函数,我们仍然需要解析参数,A请注意,我们已经知道本文的总体目的是什么:它声明了一个名为foo的函数。其余类型没有名称,因为参数的名称是可选的。

A: int *( B )()

B在哪里*(* )(int(* )(int (* )(int))).因此,要foo的参数是最外层的类型是一个空函数,该函数返回指向int的指针。大概我们会发现"某物"是一个指针,但我们仍然需要解析B来确认这一点。(好的,向前跳一点,看看B以星号开头。它是指向此空函数的指针。

B: *(* )( C )

C在哪里int(* )(int (* )(int)).这是一个指向一元函数的指针,该函数的参数是某种复杂类型,其返回值是指向我们之前解析的内容(空函数(的指针。与初始解析一样,我们发现了另一个开始阅读的地方,因为混乱已被推入参数列表。要foo的参数是指向一元函数的指针,该函数的参数是某种复杂类型,其返回值是指向返回指向int的指针的空函数的指针。

C: int(* )( D )

D在哪里int (* )(int).同样,混乱已经移动到参数列表中。此级别的东西是指向返回int的一元函数的指针。

D: int (* )(int)

最后,简单性:指向一元函数的指针,该函数接受int并返回int

所以。。。。

这将foo声明为返回一元函数的一元函数,其参数是指向一元函数的指针void返回指向一元函数的指针,返回指向int的指针的空函数,其参数是指向返回int的一元函数的指针,其参数是指向返回参数为intint的一元函数的指针。

英文版本和代码一样容易理解,不是吗? :)让我们尝试一些更有条理的东西。

  • foo
    • 回报:void
    • 参数:指向函数的指针
      • 返回:指向函数的指针
        • 返回:指向int的指针
      • 参数:指向函数的指针
        • 回报:int
        • 参数:指向函数的指针
          • 回报:int
          • 参数:int

呼。孩子们,不要在家里这样做。给你的中间类型命名,让程序员省去一些悲伤。