函数声明符(有时/总是?)是函数声明符吗? [英] Is a pointer to function (sometimes/always?) a function declarator?

查看:97
本文介绍了函数声明符(有时/总是?)是函数声明符吗?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

(此问题已从对此答案的讨论中分解出来,其中突出显示 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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆