问题描述
(这个问题是从the discussion to this answer中分离出来的,重点是CWG 1892)
该标准的某些段落将特定规则应用于函数声明符;例如[dcl.spec.auto]/3 关于占位符类型 [重点 我的]:
占位符类型可以在decl-specifier-seq、type-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 (将#修改为@)