【问题标题】:Syntax of an un-named function pointer in C++C++ 中未命名函数指针的语法
【发布时间】:2018-09-30 20:36:00
【问题描述】:

我正在研究最令人烦恼的解析,我偶然发现了这样的事情:

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

这与return-type(*name)(parameters) 的典型语法完全不同。括号是参数列表的括号,还是名称?

【问题讨论】:

  • 哦,我的 C++,语法有时会令人困惑。如果Baz 是一个没有参数且返回Foo函数,则将bar 声明为Foo 类型的变量,初始化为Baz()。但是如果Baz 是一个type 那么bar 被声明为一个函数?!疯了……
  • @RayToal 对自我推销感到抱歉,但您可能会喜欢 this parsing abuse 我去年整理的 ;)
  • 感谢自我推销!

标签: c++


【解决方案1】:

完全明确的形式:

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]),其中int [10] 也表示参数列表中的int *

【讨论】:

  • 是否应该使用一种语法而不是另一种(忽略 std::function 的使用)?如果我有一个函数指针作为参数,我应该写一个普通的函数声明并让它衰减为一个指针,还是应该只写一个函数指针声明?
  • @KrystianS 这是个人品味的问题。我更喜欢显式,所以当我的参数是指针时,我将它们声明为指针(而不是数组或函数)。
  • 您应该预先定义一个别名并在参数列表中使用它。为了大家的理智。
【解决方案2】:

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

Foo bar(Baz());
       ^     ^

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

Foo bar(Baz());
           ^^

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

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

“预调整”声明中不存在此替代指针参数声明符的高亮括号。

相关标准规则:

[dcl.fct]

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

【讨论】:

    【解决方案3】:

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

    它们用于参数列表。

    所以:

    Foo bar(Baz());
    

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

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

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

    ...

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

    ...

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-12-16
      • 1970-01-01
      • 2012-02-02
      相关资源
      最近更新 更多