出现以下问题:
c ++标准似乎说std::vector
需要一个完整的类型才能工作。 (请参阅https://en.cppreference.com/w/cpp/container/vector)那么,为什么下面的代码仍然可以编译?
#include <vector>
struct parent;
struct child
{
std::vector<parent> parents; //parent is incomplete here!
};
struct parent
{
std::vector<child> children;
};
这似乎违反直觉。如果std::vector
需要完整的类型,则std::vector<parent>
不应编译,因为在child
的类定义中仅知道其前向声明。
std::vector
不需要完整的类型吗?编辑
c ++ 11和c ++ 17之间似乎有所不同。我想了解c ++ 11版本。
答案 0 :(得分:10)
标准说(草稿N3690;这是C ++ 11之后,C ++ 14之前的版本):
[res.on.functions]
1在某些情况下(替换功能,处理程序功能, 用于实例化标准库模板的类型的操作 组件),C ++标准库取决于 一个C ++程序。如果这些组件不符合要求, 该标准对实施没有任何要求。
2特别是在以下情况下,效果未定义:
-如果在以下情况下使用不完整的类型(3.9)作为模板参数 实例化模板组件,除非特别允许 该组件。
鉴于标准没有任何要求,并且效果是不确定的(据我所知,这与未定义的行为相同),对于实例化“无效”的期望不超过对它的期望(似乎)“工作”。
自C ++ 17起,放宽了要求,并且std::vector
不要求值类型完整(如果与适当的分配器一起使用(默认分配器是适当的))。 (这种自由并不限于使用所有成员函数;它们还有其他要求)。
标准报价(当前草稿):
[vector.overview]
如果分配器满足分配器完整性要求,则在实例化矢量时可以使用不完整类型T。 在引用所得的向量专业化的任何成员之前,T必须完整。
[allocator.requirements.completeness]
如果X是类型T的分配器类,则X是否满足T是否是完整类型的分配器完整性要求:
- X是完整类型,并且
- 除value_type以外的所有allocator_trait成员类型都是完整类型。
[default.allocator]
默认分配器的所有专业化都满足分配器完整性要求([allocator.requirements.completeness])。