14

I was looking into most vexing parse, and I stumbled upon something like this:

Foo bar(Baz()); // bar is a function that takes a pointer to a function that returns a Baz and returns a Foo

This is quite different from the typical syntax of return-type(*name)(parameters). Are the parenthesis present the parenthesis for the parameter list, or are they for the name?

4

3 回答 3

17

完全显式形式:

Foo bar(Baz f());

bar是一个带单个参数f的函数,它是一个返回的函数(不带参数)Baz

不命名参数:

Foo bar(Baz ());

最终采用指向函数的指针的原因bar是函数不能按值传递,因此将参数声明为函数会自动将其衰减为指针。上面的声明等价于:

Foo bar(Baz (*)());

// or:
Foo bar(Baz (*f)());  // with a named parameter

这类似于参数列表中的void foo(int [10])whereint [10]也意味着int *

于 2018-09-30T20:46:29.373 回答
6

声明中有两组括号。外面的一组括号是函数的参数列表bar

Foo bar(Baz());
       ^     ^

Baz()在这个声明中是一个函数类型。函数类型声明中的括号分隔该函数的参数列表。

Foo bar(Baz());
           ^^

澄清一下:在函数参数声明符的上下文中,函数类型被调整为指向该类型函数的指针。所以声明实际上等价于:

Foo bar(Baz(*)());
           ^ ^

此替代指针参数声明器的突出显示的括号不存在于“预调整”声明中。

相关标准规则:

[dcl.fct]

使用以下规则确定函数的类型。每个参数的类型(包括函数参数包)由其自己的 decl-specifier-seq 和声明符确定。在确定每个参数的类型后,将任何类型为“T 数组”或函数类型T 的参数调整为“指向T 的指针”。...

于 2018-09-30T20:48:33.500 回答
3

括号是参数列表的括号,还是名称?

它们用于参数列表。

所以:

Foo bar(Baz());

声明一个函数,该函数接受一个类型函数的单个参数,该函数返回Baz并且不接受任何参数。

反过来,这等于一个函数声明,它接受一个指向函数的类型指针的单个参数,该函数返回Baz并且不接受任何参数。作为(来自函数):

参数列表中每个函数参数的类型根据以下规则确定:

...

3)如果类型是函数类型F,则替换为“指向F的指针”类型

...

于 2018-09-30T20:48:16.510 回答