使用 STL 容器的对象的前向声明

Forward declaration of objects with STL containers

考虑以下代码片段,其中第一行仅用作前向声明

 class A;

接着定义新的class

class B
{
 vector<A> Av;  //line 1
 map<int, A> Am;  //line 2
 pair<int, A> Ap; //line 3
};

第 1 行和第 2 行似乎可以使用前向声明(这可能告诉我那些容器使用指针类型的实现),而第 3 行似乎无法在 VS2012 上编译。

我的问题是行为是由标准规定的还是特定于我使用的编译器?

标准库类型的相关规则在[res.on.functions]:

In particular, the effects are undefined in the following cases: [...] if an incomplete type (3.9) is used as a template argument when instantiating a template component, unless specifically allowed for that component.

这个:

vector<A> Av;

很好。 std::vector 允许使用不完整的类型进行实例化,只要它在您使用任何成员之前变得完整即可。在 [vector.overview]:

的标准中有一个明确的例外

An incomplete type T may be used when instantiating vector if the allocator satisfies the allocator completeness requirements 17.6.3.5.1. T shall be complete before any member of the resulting specialization of vector is referenced.

std::liststd::forward_list 有相似的措辞。

这个:

map<int, A> Am;

格式错误。 std::map 根据第一个引号,在实例化时需要一个完整的类型。对于 vector.

的方式,此容器也不例外

这个:

pair<int, A> Ap;

不可能工作,因为 pair 只是一个有两个成员的简单结构。为了拥有 A 类型的成员,您需要一个完整的类型。

不,这种行为是预期的和标准的。

合理的是std::pair实际上形成了一个结构体,因此在实例化之前它的两个类型必须是完整的。

[作为 Barry 回答的补充说明]

根据标准(C++17),在实例化时只有std::vectorstd::liststd::forward_list可以使用不完整的类型。

§23.3.11.1/3 Class 模板向量概述 [vector.overview]:

An incomplete type T may be used when instantiating vector if the allocator satisfies the allocator completeness requirements [allocator.requirements.completeness]. T shall be complete before any member of the resulting specialization of vector is referenced.

§23.3.9.1/4 Class 模板 forward_list 概述 [forwardlist.overview]:

An incomplete type T may be used when instantiating forward_list if the allocator satisfies the allocator completeness requirements [allocator.requirements.completeness]. T shall be complete before any member of the resulting specialization of forward_list is referenced.

§23.3.10.1/3 Class 模板列表概述 [list.overview]:

An incomplete type T may be used when instantiating list if the allocator satisfies the allocator completeness requirements [allocator.requirements.completeness]. T shall be complete before any member of the resulting specialization of list is referenced.