这是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中合法化,编译器通常也不会诊断。为了澄清,我只想问问在类型本身的定义中使用不完整类型,如所示示例。
最佳答案
这取决于确切的规则。必须诊断出该标准核心语言部分中与不完整类类型有关的大多数规则违规。除非另有说明,否则将其用作标准库模板的模板参数是未定义的行为,这为实现提供了更大的自由度。
这些规则需要诊断(因为它们用“应”表示):
[basic.def]/5:
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.
[dcl.fct.def.general]/2:
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
定义的,因此这也适用于->
运算符表达式。[class.mem]/15:
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(关于类定义的基类列表):
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.
禁止不完整类类型的核心语言规则更多,但以上是最常见的规则。另请参阅[basic.def.odr]/12中需要完整类的上下文的非规范列表。
我没有看到直接的规则,即如果
scope::name
命名不完整的类类型,则合格ID的scope
格式不正确,但在这种情况下,名称查找肯定会失败,这是可诊断的违规。对于标准库,整体禁止将不完整类型用作模板参数是[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添加了实例化类
std::vector<T, Alloc>
的特定权限,但如果T
不完整且Alloc
满足“分配器完整性要求”([vector.overview]/4),则其成员均不实例化。
关于c++ - 是否需要诊断使用不完整的类型?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/61356736/