【问题标题】:In the standard, what is "derived-declarator-type"?在标准中,什么是“派生声明符类型”?
【发布时间】:2023-03-16 22:37:01
【问题描述】:

在 C++ (C++11) 标准的不同地方,声明是根据 derived-declarator-type-list 来描述的。我正在研究右值引用,在这种情况下使用这个术语是至关重要的(第 8.3.2 节):

T D 声明中,其中 D 具有任何一种形式
& 属性说明符序列opt D1
&& attribute-specifier-seqoptD1
以及声明中标识符的类型T D1是 “derived-declarator-type-list T”,然后是D的标识符的类型 是“derived-declarator-type-listT 的引用。”

不幸的是,标准中从未定义“derived-declarator-type”类别。 (我查看了“派生”一词的所有用法,此外,这可能已得到证实herehere。)

因为“derived-declarator-type-list”是斜体,我假设它指的是一个类别,而不是变量标签,例如 T (因此,我不同意 Doug Gwyn 在我刚刚给出的第二个链接中的评估,即“我们可以使用 X 而不是 'derived-declarator-type-list' ")。

derived-declarator-type在C++11标准中的定义是什么?

【问题讨论】:

  • 我没有令人信服的论据,但我将 derived-declarator-type 解释为指一组英文短语,如“pointer to”或“function with no参数返回”用于类型的英文描述。
  • 我刚刚发布了question and answer 以进一步澄清这一点!
  • 太棒了!太好了。

标签: c++ c++11 standards


【解决方案1】:

它被立即定义。这是一种将T 之前出现的任何内容转移到下一个类型的方式,类似于:

<some stuff> T
<some stuff> reference to T

它只是 T 之前的 T D1 类型中的任何内容。

例如,如果您有声明int&amp; (*const * p)[30],则TintD&amp; (*const * p)[30]D1(*const * p)[30]T D1 的类型是“指向 30 int 数组的 const 指针的指针”。因此,根据您引用的规则,p 的类型是“指向 30 引用 int 数组的 const 指针的指针”。

当然,该声明随后被 §3.4.2/5 禁止:

不得有对引用的引用,不得有引用数组,也不得有指向引用的指针。

我认为它是 派生 声明类型列表的非正式术语来自 C 标准对 派生类型 的定义(类似于 C++ 中的复合类型):

任何数量的派生类型都可以从对象、函数和 不完整的类型,如下:

  • 数组类型 [...]
  • 结构类型 [...]
  • 联合类型 [...]
  • 一个函数类型 [...]
  • 指针类型 [...]

回应 cmets:您似乎对类型和声明符感到困惑。例如,如果 int* p 是声明符,那么 p 的类型是“指向 int 的指针”。类型表示为这些类似英语的句子。

示例 1int *(&amp;p)[30]

这是一个声明 T D 其中(§8.3.1 指针):

  • T -> int
  • D -> *(&amp;p)[3]

D 的形式为:

* attribute-specifier-seqopt cv-qualifier-seqopt D1

其中D1(&amp;p)[3]。这意味着T D1 的形式为int (&amp;p)[3],其类型为“对3 int 的数组的引用”(您可以递归地解决这个问题,下一步使用§8.3.4 数组等等)。 int 之前的所有内容都是 derived-declarator-type-list。因此我们可以推断出我们原始声明中的p 的类型为“对数组的引用3 指向int 的指针”。魔法!

示例 2float (*(*(&amp;e)[10])())[5]

这是一个声明 T D 其中(第 8.3.4 节数组):

  • T -> float
  • D -> (*(*(&amp;e)[10])())[5]

D 的形式为:

D1 [ constant-expressionopt ] attribute-specifier-seqopt

其中D1(*(*(&amp;e)[10])())。这意味着T D1 的形式为float (*(*(&amp;e)[10])()),其类型为“对 10 个指向 () 函数的指针的数组的引用,该函数返回指向浮点的指针”(您可以通过应用 §8.3/6 和 §8.3.1 指针来计算)等等)。 float 之前的所有内容都是 derived-declarator-type-list。因此我们可以推断出我们原始声明中的p 具有类型“对10 个数组的引用,该函数指向() 返回指向5 个浮点数组的指针”。再次魔法!

【讨论】:

  • 也许吧。但它遵循语法类别的符号约定(斜体、破折号、“列表”),而且“派生”这个词很可能代表某种东西,至少是非正式的。
  • @DanNissenbaum 在这种情况下添加了关于“派生”含义的编辑。
  • 这看起来很划算,谢谢。对我来说有一个“松散的链接”:鉴于在您的示例中,T D1 的类型是“指向 30 int 数组的 const 指针的指针”,下一步该类型将被分解为“派生-declarator-type-list T”(假设后者 T 代表不同的类型),但没有解释如何分解它。在我看来,另一个同样有效的分解,例如, 是:derived-declarator-type-list 是“指向 const 指针的指针”,新的 T 是“30 个 int 的数组”,结果有所不同。有什么想法吗?
  • @DanNissenbaum "derived-declarator-type-list T" 中的 TT D1 中的相同。 T D1 中的 T 在 §8.3 中定义为声明的 attribute-specifier-seq_opt decl-specifier-seq 部分。在我给出的这个例子中,它就是int。基本上,T 是在所有声明符之间共享的声明的一部分(例如 int x, y, *z)。
  • @DanNissenbaum 我应该放入一些参考资料。这不仅是查看 §8.3.2 参考资料,还查看 §8.3 的所有其他部分。事实上,该示例使用 §8.3.1 指针,它允许T D 其中D 具有* D1 的形式。 §8.3 的所有部分都递归地应用于声明以确定类型。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-11-02
  • 2011-04-02
  • 2016-07-15
  • 2012-11-17
相关资源
最近更新 更多