指向函数的指针有时/总是?是函数声明符吗?

问题描述

(这个问题是从the discussion to this answer中分离出来的,重点是CWG 1892


该标准的某些段落将特定规则应用于函数声明符;例如[dcl.spec.auto]/3 关于占位符类型 [重点 我的]:

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

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

int f() { return 0; }
auto (*g)() = f;  // #1

GCC 和 Clang 都接受,将 g 推导出 int(*)()

  • 指向函数的指针(有时/总是?)是函数声明符吗?
  • 或者,或者,应用到示例中,应该按照 [dcl.spec.auto]/3 拒绝 #1,还是后者不适用此处,因为指向函数的指针不是函数声明符(而是允许 {{ 1}} 根据 [dcl.spec.auto]/4 关于从初始值设定项推导的变量类型)?

什么是给定声明符的规则并不完全容易遵循,但我们可以注意到,从 [dcl.decl]/1

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

给定的声明符是变量声明符函数声明符类型声明符中的任何一种。

  • [dcl.ptr] 涵盖了作为指针的(变量)声明符,但没有明确(/规范地)提及指向函数的指针,尽管在 [dcl.ptr]/4 中以非规范方式这样做了
  • [dcl.fct] 涵盖了函数声明符,但没有提到函数指针作为函数声明的一部分,只是指出在函数指针的赋值/初始化期间检查函数类型(这与函数声明符是什么无关) )

我的解释是 #1 是合法的(根据当前标准),因为它属于变量声明符。如果这实际上是正确的,那么扩展问题(来自链接的线程)是

#1

是否合法(/根据 CWG 1892 是否合法);因为模板参数可以说包含一个声明符,它是一个函数指针声明符,而不是一个函数声明符。

我们终于可以注意到,正如链接到答案中所指出的那样,

template<auto (*g)()> 
int f() { return g(); }

可以说是格式错误的(尽管这个例子也被 GCC 和 Clang 接受),因为 template<auto g()> // #2 int f() { return g(); } 处的非类型模板参数是一个函数声明符,因此根据 [ dcl.spec.auto]/3,因为它不包含尾随返回类型并且不声明函数。

解决方法

暂无找到可以解决该程序问题的有效方法,小编努力寻找整理中!

如果你已经找到好的解决方法,欢迎将解决方案带上本链接一起发送给小编。

小编邮箱:dio#foxmail.com (将#修改为@)