C++ 指向函数的指针(有时/总是?)是函数声明器吗?

C++ 指向函数的指针(有时/总是?)是函数声明器吗?,c++,language-lawyer,auto,type-deduction,C++,Language Lawyer,Auto,Type Deduction,(此问题已从中突破,突出显示) 本标准的某些段落将特定规则应用于函数声明器;e、 g.关于占位符类型[强调[/strong>我的]: 占位符类型可以与函数声明符一起出现在decl说明符seq、类型说明符seq、转换函数id或尾部返回类型中,在此类声明符有效的任何上下文中。如果函数声明符包含尾部返回类型([dcl.fct]),则该尾部返回类型指定函数的声明返回类型否则,函数声明器应声明函数。[…] 限制占位符类型与函数声明符一起出现的位置。我们可以研究以下例子: int f() { return

(此问题已从中突破,突出显示)


本标准的某些段落将特定规则应用于函数声明器;e、 g.关于占位符类型[强调[/strong>我的]:

占位符类型可以与函数声明符一起出现在decl说明符seq、类型说明符seq、转换函数id或尾部返回类型中,在此类声明符有效的任何上下文中。如果函数声明符包含尾部返回类型([dcl.fct]),则该尾部返回类型指定函数的声明返回类型否则,函数声明器应声明函数。[…]

限制占位符类型与函数声明符一起出现的位置。我们可以研究以下例子:

int f() { return 0; }
auto (*g)() = f;  // #1
GCC和Clang都接受,将
g
推断为
int(*)(

  • 指向函数的指针(有时/总是?)是函数声明器吗
  • 或者,应用于示例,是否应根据拒绝
    #1
    ,或者后者不适用于此处,因为函数的指针不是函数声明符(而是允许
    #1
    根据从初始值设定项中扣除变量类型)

给定声明符的规则并不完全容易遵循,但我们可能会注意到,从

声明器在声明中声明单个变量、函数或类型

给定的声明器是变量声明器、函数声明器或类型声明器中的任意一个

  • 涵盖作为指针的(变量)声明器,但没有明确(/规范性地)提到函数指针,尽管在
  • 涵盖函数声明器,但未提及函数指针作为函数声明的一部分,除了在函数指针赋值/初始化过程中检查函数类型的说明(这与函数声明器的内容无关)
我的解释是,
#1
是合法的(根据当前标准),因为它属于变量声明器。如果这实际上是正确的,那么扩展问题(来自链接线程)是

template<auto (*g)()> 
int f() { return g(); }
模板
int f(){return g();}
是否合法(/根据CWG 1892,是否打算合法);因为模板参数包含一个声明器,它是一个函数指针声明器,而不是一个函数声明器

最后,我们可能会注意到,正如链接到的答案中同样指出的那样

template<auto g()>  // #2
int f() { return g(); }
template/#2
int f(){return g();}

可以说是格式错误(尽管GCC和Clang也接受此示例),因为
#2
处的非类型模板参数是一个函数声明符,因此根据[dcl.spec.auto]/3在非法上下文中使用,因为它不包含尾随返回类型,也不声明函数。

这里的混淆源于“declarator”的两种不同含义:一种是声明的一部分(在说明符之后),属于一个实体(或typedef name),而另一种是用来构成前一种的几种句法结构中的任何一种。后一种含义产生了语法产品ptr声明符(也包括引用)和noptr声明符(包括函数和数组)。这一意义对于赋予“函数声明者应声明函数”的限制的任何意义也是必要的。此外,如果我们使用变量声明

auto (*g)() = /*…*/;
为了不涉及[dcl.spec.auto.general]/3中的“函数声明器”,我们将无法编写

auto (*g)() -> int;
这是普遍接受的(就像问题中的类似例子一样)

此外,虽然检查“函数声明器是否包含尾部返回类型”的语句不可避免地引用了总体声明器(支持尾部返回类型),但它是以“声明运算符”的身份这样做的因为它仍然允许在上述情况下嵌套使用此类运算符。(这一限制所禁止的是公正

auto *f() -> int*;
在这里,扣减是可行的,但根本不执行,因为扣减总是无用的。)


同时,除了实现共识之外,还有一些证据表明,更高级别问题的答案是,在这些情况下,应该允许
auto
,[dcl.spec.auto.general]/1表示函数参数中的
auto
用于声明通用lambda或缩写函数模板“如果它不是引入尾部返回类型的
auto
类型说明符”,而不是如果它根本不与函数声明符一起使用。

我的理解是
auto(*g)(=f;
工作的原因与
auto x=42;
工作的原因相同,而不是因为它与函数有关。事实上,
auto x=42,(*g)(=f;
@IgorTandetnik为了清晰起见:我们讨论的是格式良好的声明,而不是什么是有效的(这些在语言律师问题中通常存在冲突)。我也倾向于格式良好的
auto(*g)(=f
),关键是声明中不涉及函数声明符(例如[dcl.spec.auto]/3不适用)。您的第二个示例在这里是且不是重要的;讨论的单个声明符是格式良好的还是格式不良的(单独使用还是作为具有多个声明符的decl.的一部分)。在其声明中没有涉及函数声明符
auto(*g)(
是如何解析的?@languagelayer”倾向于…………没有函数声明器“-这是我的关键问题:这里实际上有一个函数声明器吗?”/是函数指针,还是包含函数声明器?