10

在 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 表达式中不能定义类型的规则在哪里?

4

2 回答 2

8

在 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 类型说明符序列不应定义类或枚举,除非它出现在 type-不是模板声明的声明的别名声明 (7.1.3) 的 id。

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

于 2014-01-07T20:38:48.997 回答
3

从 N3797:

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

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

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

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

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

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

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

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

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

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

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

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

于 2014-01-07T20:39:09.240 回答