函数声明符(有时/总是?)是函数声明符吗? [英] Is a pointer to function (sometimes/always?) a function declarator?
问题描述
(此问题已从对此答案的讨论中分解出来,其中突出显示 CWG 1892 )
(This question has been broken out from the discussion to this answer, which highlights CWG 1892)
该标准的某些段落将特定规则应用于功能声明符;例如 [dcl.spec.auto]/3 关于占位符类型[强调我的]:
Some paragraphs of the standard applies specific rules to function declarators; e.g. [dcl.spec.auto]/3 regarding placeholder types [emphasis mine]:
占位符类型可以与函数声明符一起出现在 decl-specifier-seq , type-specifier-seq ,中在此类声明符有效的任何情况下,conversion-function-id 或 trailing-return-type .如果函数声明符包含 trailing-return-type ([dcl.fct]),则该 trailing-return-type 指定函数的声明返回类型.否则,函数声明器应声明一个函数. [...]
The placeholder type can appear with a function declarator in the decl-specifier-seq, type-specifier-seq, conversion-function-id, or trailing-return-type, in any context where such a declarator is valid. If the function declarator includes a trailing-return-type ([dcl.fct]), that trailing-return-type specifies the declared return type of the function. Otherwise, the function declarator shall declare a function. [...]
限制在函数声明符中(可能在其中)占位符类型出现的位置.我们可以研究以下示例:
restricts where placeholder types may appear with(in) a function declarator. We may study the following example:
int f() { return 0; }
auto (*g)() = f; // #1
GCC和Clang都接受的
,将 g
推导出为 int(*)()
.
which both GCC and Clang accepts, deducing g
to int(*)()
.
- 指向函数的指针(有时/总是?)是函数声明符吗?
- 或者作为替代,应用于该示例,应该按照 [dcl.spec.auto]/4 关于从初始值设定项中推断变量类型)?
- Is a pointer to function (sometimes/always?) a function declarator?
- Or, alternatively, applied to the example, should
#1
be rejected as per [dcl.spec.auto]/3, or does the latter not apply here as a pointer to function is not a function declarator (instead allowing#1
as per [dcl.spec.auto]/4 regarding variable type deduction from initializer)?
关于给定声明符的规则并不完全容易遵循,但是我们可能会注意到,来自
The rules for what is a given declarator is not entirely easy to follow, but we may note that, from [dcl.decl]/1
声明器在声明中声明单个变量,函数或类型.
A declarator declares a single variable, function, or type, within a declaration.
给定的声明符是变量声明符,函数声明符或类型声明符中的任何一个.
that a given declarator is either any of a variable declarator, a function declarator or a type declarator.
- [dcl.ptr] 涵盖了(变量)声明符是指针,但没有明确(/规范地)提及函数指针,尽管在 [dcl.fct] 涵盖了函数声明符,但没有提及将函数指针作为函数声明的一部分,但要注意,在分配/初始化函数指针时会检查函数类型(与函数声明符无关)
- [dcl.ptr] covers (variable) declarators that are pointers, but does not explicitly (/normatively) mention pointers to functions, albeit does so non-normatively in [dcl.ptr]/4
- [dcl.fct] covers function declarators but does not mention function pointers as part of function declarations, other than a note that function types are checked during assignment/initialization to function pointers (which is not relevant for what a function declarator is)
我的解释是,#1
是合法的(按照当前标准),因为它属于变量声明符.如果这实际上是正确的,那么扩展的问题(来自链接的线程)是
My interpretation is that #1
is legal (as per the current standard), as it falls under a variable declarator. If this is actually correct, then the extended question (from the linked thread) is whether
template<auto (*g)()>
int f() { return g(); }
是否合法(/根据CWG 1892的规定,是否合法);因为模板参数可以包含一个声明符,它是一个函数指针声明符,而不是一个函数声明符.
is legal or not (/intended to be legal or not as per CWG 1892); as the template parameter arguably contains a declarator that is a function pointer declarator, and not a function declarator.
我们终于可以注意到,正如答案链接中所指出的那样,
We may finally note, as similarly pointed out in the linked to answer, that
template<auto g()> // #2
int f() { return g(); }
的格式可能不正确(尽管此示例也为GCC和Clang所接受),因为#2
处的非类型模板参数是函数声明符,因此在非法中使用根据[dcl.spec.auto]/3的上下文,因为它不包含结尾的返回类型,并且没有声明函数.
is arguably ill-formed (although this example is also accepted by both GCC and Clang), as the non-type template parameter at #2
is a function declarator and is thus used in an illegal context as per [dcl.spec.auto]/3, as it does not contain a trailing return type and does not declare a function.
推荐答案
此处的混淆是由"declarator"的两种不同含义引起的:一种是声明的一部分(在指定者之后),属于一个实体(或typedef-name),而另一个是用于构成前一种的几种语法构造中的任何一种.后一种含义产生了语法产生 ptr-declarator (也包括参考文献)和 noptr-declarator (包括函数和数组).为了赋予功能声明者应声明功能"的限制任何含义,该含义也是必要的.而且,如果我们使用变量声明
The confusion here arises from two different meanings of "declarator": one is the portion of a declaration (after the specifiers) that pertains to one entity (or typedef-name), while the other is any of the several syntactic constructs used to form the former kind. The latter meaning gives rise to the grammar productions ptr-declarator (which also covers references) and noptr-declarator (which includes functions and arrays). That meaning is also necessary to give any meaning to a restriction that a "function declarator shall declare a function". Moreover, if we took the variable declaration
auto (*g)() = /*…*/;
不涉及功能声明器"出于[dcl.spec.auto.general]/3的目的,我们将无法编写
to not involve a "function declarator" for the purposes of [dcl.spec.auto.general]/3, we would not be able to write
auto (*g)() -> int;
这是普遍接受的(就像问题中的类似示例一样.)
which is universally accepted (just as is the similar example in the question).
此外,在检查函数声明符是否包含 trailing-return-type "的语句的同时,不可避免地指代整体 声明符(支持 trailing-return-type 的东西),它的作用是声明操作符"因为它仍然允许上述情况与此类运算符的嵌套使用.(该限制禁止的只是
Moreover, while the statement that checks whether "the function declarator includes a trailing-return-type" inevitably refers to an overall declarator (which is what supports a trailing-return-type), it does so in its capacity as a "declaration operator" because it still allows the above cases with nested use of such operators. (What that limitation forbids is just
auto *f() -> int*;
可以进行推论,但在这里根本不执行推论,因为它总是无用的.)
where deduction would work but isn't performed at all here because it would always be useless.)
与此同时,除了实现共识之外,还有一些证据表明,对上级问题的答案是在这种情况下应允许 auto
:spec.auto.general]/1表示,函数参数中的 auto
用于声明通用lambda或缩写的函数模板如果不是 auto
类型说明符引入了 trailing-return-type "而不是完全不与函数声明符一起使用.
Meanwhile, there is some evidence, beyond implementation consensus, that the answer to the higher-level question is that auto
in these cases should be allowed: [dcl.spec.auto.general]/1 says that auto
in a function parameter serves to declare a generic lambda or abbreviated function template "if it is not the auto
type-specifier introducing a trailing-return-type" rather than if it is not used with a function declarator at all.
这篇关于函数声明符(有时/总是?)是函数声明符吗?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!