【问题标题】:C++11 standard ref for allowed type definitions in type specifier uses?类型说明符使用中允许的类型定义的 C++11 标准参考?
【发布时间】:2014-01-07 19:34:28
【问题描述】:

在 C++11 中,类型说明符包括类说明符枚举说明符。 (又名类定义和枚举定义)

根据语法/句法 - 类型说明符可以出现在语言的多个地方,但并非所有这些地方都允许使用类说明符和枚举说明符。

例如:

struct C{} c;
// ok: types may be defined in the specifiers of a simple declaration

void f(struct S{});
// error: types may not be defined in parameter types

constexpr auto i = sizeof(enum E{});
// error: types may not be defined in ‘sizeof’ expressions

它在标准中的什么地方将类型说明符的这些用途划分为可以定义和不可以定义的类型?例如,在 sizeof 表达式中不能定义类型的规则在哪里?

【问题讨论】:

  • 大概对于sizeof来说,至少这可以从5.3/1中指定的Unary expressions语法推断出来,但粗略看下并不明显(由于递归定义)。
  • +1,好问题。但是阅读关于这个特定主题的标准是相当令人迷惑的,到处都是参考。顺便说一句,你能举一个你真正需要这些东西的例子吗? IOW,是否总是可以将定义分成两部分?
  • @MarkB: sizeof(type-id) -> type-id -> type-specifer-seq -> type-specifier -> class-specifier。附录A是一个语法总结。从语法上讲,它是允许的,所以在某处必须有一些文字说明您不能在那里定义类型。
  • 啊,如果只有 Clang 4.X 会在编译器错误中显示标准引用 ;-)
  • @TemplateRex:实际上这不是一个坏主意。不过,做匹配需要做很多工作。

标签: c++ c++11 language-lawyer specifier type-declaration


【解决方案1】:

在 C++ 标准中找不到它的原因是因为它实际上在 C 标准的增量中被禁止。

在 C.1.4 中,我们有以下内容:Change: Types must be declared in declarations, not in expressions In C, a sizeof expression or cast expression may create a new type.,它显示了相关的禁令。

这在 7.1.6/3 中明确指出:

至少需要一个不是 cv 限定符的类型说明符 声明,除非它声明了构造函数、析构函数或 转换函数。92 类型说明符序列不应定义类 或枚举,除非它出现在 alias-declaration (7.1.3) 不是 a 的声明 模板声明。

特别感兴趣的部分是A type-specifier-seq shall not define a class or enumeration unless...

【讨论】:

  • 遗憾的是,该部分是 informative 而不是 normative - 它旨在告诉您文档的其余部分所说的内容,它不应该定义新信息。我尝试并未能找到它的 normative 文本。
  • @hvd:不,它是一个 decl-specifer-seq,一个 decl-specifier-seq 永远不是一个类型说明符序列,尽管 decl-specifier 有时是一个类型说明符。
  • @AndrewTomazos 啊,谢谢,它是一个类型说明符(一个decl说明符可以是一个类型说明符)但不是一个类型说明符序列。
  • 有趣的是,这似乎允许在 for-range-declaration 中进行类型定义:for (struct S2 {} s2: s) { },它被 GCC 接受,-std=c++11 -pedantic 没有任何诊断,但对于哪个clang给出了一个明确的“错误:类型可能没有在for range声明中定义”
  • @hvd:除非有一些额外的文本,否则Clang是错误的,它是一个decl-specifier-seq,既不是返回类型也不是参数类型。
【解决方案2】:

来自 N3797:

8.3.5/9 类型不应在返回或参数类型中定义。函数定义的参数类型或返回类型应 不是不完整的类类型(可能是 cv 限定的),除非 函数被删除( 8.4.3 )或定义嵌套在该类的成员规范中(包括定义的嵌套类中的定义) 类)。

这会阻止在函数声明中定义新类型。

接下来的两个是 OP 未提及的其他极端情况:

11.3/2 类不应在友元声明中定义。

14.1/2 类型不应在模板参数声明中定义。

最后,这个子句在sizeof 和其他地方阻止了它:

7.1.6/3 类型说明符序列不应定义类或枚举,除非它出现在 不是模板声明的声明的别名声明(7.1.3)

请注意,C 没有该限制 (C.1.4)

此外,在 C++ 标准的早期版本中,我们有:

5.3.3p5 类型不应在 sizeof 表达式中定义

我在最新版本的标准提案中找不到,它在 N3797 下是多余的,因为 sizeofs 在语法中定义类型的路由是通过 type-specifier-seq,并被 7.1.6/3 阻止:

sizeof(type-id) -> type-id -> type-specifer-seq -> type-specifier -> class-specifier

【讨论】:

  • sizeof 始终是一个表达式,因此Types shall not be defined in a sizeof expressionTypes must be declared in declarations, not in expressions. 来说是多余的
猜你喜欢
  • 1970-01-01
  • 2016-07-31
  • 1970-01-01
  • 1970-01-01
  • 2022-01-14
  • 1970-01-01
  • 2021-07-11
  • 2022-01-17
  • 1970-01-01
相关资源
最近更新 更多