给定一个不完整的类型:
struct S;
然后,以下声明是:S *p; // ok, pointer to incomplete types is allowed
std::deque<S> l; // error, instantiating std::deque with incomplete type is UB
但是以下声明呢?std::deque<S> *p; // seems to be UB like the previous case,
// but is it ok if p is not used till S is defined?
std::deque<S*> p; // not really sure about this one
编辑:问题使用了std::list
而不是std::deque
,但这违背了问题的目的,因为std::list
明确地是allowed以使用不完整的类型。 std::deque
似乎没有这样的permission。
最佳答案
std::deque<S> *p; // seems to be UB like the previous case, // but is it ok if p is not used till S is defined?
这实际上是有趣的地方。是的,实例化,即不允许使用类型不完整的容器,对此没有任何规定。但是问题在于它是否真的被实例化了。根据核心语言,不一定必须如此。
[temp.inst]
1 Unless a class template specialization has been explicitly instantiated or explicitly specialized, the class template specialization is implicitly instantiated when the specialization is referenced in a context that requires a completely-defined object type or when the completeness of the class type affects the semantics of the program.
指向类型的指针不需要该类型是完整的。因此,仅靠该声明通常不足以导致类模板的实例化,因此确定此处违反容器的要求可能为时过早。
当然,除非我们采取“类类型的完整性会影响程序的语义”的原则,否则将违反契约(Contract)的行为包括在标准库中。我想一个实现可以在这里实例化。我不知道有任何实现,所以这可能不是欲望的解释。
因此,为了谨慎起见,我也认为此UB也是如此。
std::deque<S*> p; // not really sure about this one
这可以。不管
S
是否完整,S*
仍然是完整的对象类型。我之所以这样说,是因为它不包含在[basic.types]
5 A class that has been declared but not defined, an enumeration type in certain contexts ([dcl.enum]), or an array of unknown bound or of incomplete element type, is an incompletely-defined object type. Incompletely-defined object types and cv void are incomplete types ([basic.fundamental]). Objects shall not be defined to have an incomplete type.
仅在尝试在执行解引用或指针算术的表达式中使用此类指针时,才会出现有关
S
完整性的约束。但是指针类型本身仍然是完整的。因此,这是容器类型的有效模板参数。
关于c++ - 标准库容器和不完整类型的规则是什么?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/63061188/