为什么std :: vector在类定义中使用不完整的类型?

时间:2019-07-10 17:05:15

标签: c++ c++11 language-lawyer std stdvector

出现以下问题:

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不需要完整的类型吗?
  • 或者,这只是a幸吗?从技术上讲,这是不允许的,但是无论如何它都适用于所有实现...

编辑

c ++ 11和c ++ 17之间似乎有所不同。我想了解c ++ 11版本。

1 个答案:

答案 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])。