在其自己的定义中使用不完整类型是否需要诊断?
Does using an incomplete type within its own definition require a diagnostic?
这是 this 问题的语言律师跟进,所有答案都同意以下内容 不允许 :
struct A { A a; };
有几种情况可以在类型定义本身中使用不完整的类型,例如
struct A { A *a; };
struct A { A &a; };
struct A { std::unique_ptr<A> a; };
struct A { std::vector<A> a; }; // since c++17
等等
我的问题是,是否需要编译器来诊断以不允许的方式使用不完整类型的程序?即它是病态的吗?或者这些程序有UB吗?或者别的什么?
我的感觉是,某些情况只是 UB,例如 vector
示例,编译器通常不会对其进行诊断,即使它仅在 c++17 中合法化。
为了澄清,我只是询问在类型本身的定义中使用不完整的类型,如所示示例。
这取决于确切的规则。必须诊断违反标准核心语言部分中与不完整 class 类型相关的大多数规则。除非另有说明,否则用作标准库模板的模板参数是未定义的行为,这为实现提供了更多的自由度。
这些规则需要诊断(因为它们用“应”声明):
In the definition of an object, the type of that object shall not be an incomplete type ([basic.types]), an abstract class type, or a (possibly multi-dimensional) array thereof.
The type of a parameter or the return type for a function definition shall not be a (possibly cv-qualified) class type that is incomplete or abstract within the function body unless the function is deleted ([dcl.fct.def.delete]).
[expr.ref]/4(关于.
运算符前的操作数表达式的类型):
The class type shall be complete unless the class member access appears in the definition of that class. [ Note: If the class is incomplete, lookup in the complete class type is required to refer to the same declaration ([basic.scope.class]). — end note ]
由于 ->
运算符的内置含义定义为 A->B
等同于 (*A).B
,这也适用于 ->
运算符表达式。
The type of a non-static data member shall not be an incomplete type ([basic.types]), an abstract class type ([class.abstract]), or a (possibly multi-dimensional) array thereof. [ Note: In particular, a class C cannot contain a non-static member of class C, but it can contain a pointer or reference to an object of class C. — end note ]
[class.derived]/2(关于 class 定义的基础 class 列表):
A class-or-decltype shall denote a (possibly cv-qualified) class type that is not an incompletely defined class ([class.mem]); any cv-qualifiers are ignored.
还有更多核心语言规则禁止不完整的 class 类型,但以上是最常见的相关规则。另请参阅 [basic.def.odr]/12.
中需要完整 class 的非规范上下文列表
如果 scope
命名不完整 [=60=,我没有看到 qualified-id scope::name
格式不正确] 类型,但在这种情况下名称查找肯定会失败,这是可诊断的违规行为。
对于标准库,对不完整类型作为模板参数的总体禁止是 [res.on.functions]/(2.5):
In certain cases (replacement functions, handler functions, operations on types used to instantiate standard library template components), the C++ standard library depends on components supplied by a C++ program. If these components do not meet their requirements, this document places no requirements on the implementation.
In particular, the effects are undefined in the following cases:
...
If an incomplete type ([basic.types]) is used as a template argument when instantiating a template component or evaluating a concept, unless specifically allowed for that component.
如前所述,C++17 添加了实例化 class std::vector<T, Alloc>
的特定权限,但其成员的 none,如果 T
不完整且 Alloc
满足“分配器完整性要求”([vector.overview]/4)
这是 this 问题的语言律师跟进,所有答案都同意以下内容 不允许 :
struct A { A a; };
有几种情况可以在类型定义本身中使用不完整的类型,例如
struct A { A *a; };
struct A { A &a; };
struct A { std::unique_ptr<A> a; };
struct A { std::vector<A> a; }; // since c++17
等等
我的问题是,是否需要编译器来诊断以不允许的方式使用不完整类型的程序?即它是病态的吗?或者这些程序有UB吗?或者别的什么?
我的感觉是,某些情况只是 UB,例如 vector
示例,编译器通常不会对其进行诊断,即使它仅在 c++17 中合法化。
为了澄清,我只是询问在类型本身的定义中使用不完整的类型,如所示示例。
这取决于确切的规则。必须诊断违反标准核心语言部分中与不完整 class 类型相关的大多数规则。除非另有说明,否则用作标准库模板的模板参数是未定义的行为,这为实现提供了更多的自由度。
这些规则需要诊断(因为它们用“应”声明):
In the definition of an object, the type of that object shall not be an incomplete type ([basic.types]), an abstract class type, or a (possibly multi-dimensional) array thereof.
The type of a parameter or the return type for a function definition shall not be a (possibly cv-qualified) class type that is incomplete or abstract within the function body unless the function is deleted ([dcl.fct.def.delete]).
[expr.ref]/4(关于.
运算符前的操作数表达式的类型):
The class type shall be complete unless the class member access appears in the definition of that class. [ Note: If the class is incomplete, lookup in the complete class type is required to refer to the same declaration ([basic.scope.class]). — end note ]
由于 ->
运算符的内置含义定义为 A->B
等同于 (*A).B
,这也适用于 ->
运算符表达式。
The type of a non-static data member shall not be an incomplete type ([basic.types]), an abstract class type ([class.abstract]), or a (possibly multi-dimensional) array thereof. [ Note: In particular, a class C cannot contain a non-static member of class C, but it can contain a pointer or reference to an object of class C. — end note ]
[class.derived]/2(关于 class 定义的基础 class 列表):
A class-or-decltype shall denote a (possibly cv-qualified) class type that is not an incompletely defined class ([class.mem]); any cv-qualifiers are ignored.
还有更多核心语言规则禁止不完整的 class 类型,但以上是最常见的相关规则。另请参阅 [basic.def.odr]/12.
中需要完整 class 的非规范上下文列表如果 scope
命名不完整 [=60=,我没有看到 qualified-id scope::name
格式不正确] 类型,但在这种情况下名称查找肯定会失败,这是可诊断的违规行为。
对于标准库,对不完整类型作为模板参数的总体禁止是 [res.on.functions]/(2.5):
In certain cases (replacement functions, handler functions, operations on types used to instantiate standard library template components), the C++ standard library depends on components supplied by a C++ program. If these components do not meet their requirements, this document places no requirements on the implementation.
In particular, the effects are undefined in the following cases:
...
If an incomplete type ([basic.types]) is used as a template argument when instantiating a template component or evaluating a concept, unless specifically allowed for that component.
如前所述,C++17 添加了实例化 class std::vector<T, Alloc>
的特定权限,但其成员的 none,如果 T
不完整且 Alloc
满足“分配器完整性要求”([vector.overview]/4)