使用STL容器转发对象的声明

use*_*155 6 c++ stl forward-declaration std-pair visual-studio-2012

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

 class A;
Run Code Online (Sandbox Code Playgroud)

然后定义新类

class B
{
 vector<A> Av;  //line 1
 map<int, A> Am;  //line 2
 pair<int, A> Ap; //line 3
};
Run Code Online (Sandbox Code Playgroud)

第1行和第2行似乎没有前向声明(这可能告诉我那些容器使用指针类型的实现),其中第3行似乎不在VS2012上编译.

我的问题是标准或特定于我正在使用的编译器所规定的行为?

谢谢

Bar*_*rry 11

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

特别是,在以下情况下,效果未定义:[...]如果在实例化模板组件时将不完整类型(3.9)用作模板参数,除非特别允许该组件.

这个:

vector<A> Av;
Run Code Online (Sandbox Code Playgroud)

很好.std::vector允许使用不完整的类型进行实例化,只要它在您使用任何成员之前完成即可.在[vector.overview]中的标准中有一个明确的例外:

如果分配器满足分配器完整性要求17.6.3.5.1,则T在实例化时可以使用不完整类型vector.T在引用向量专业化的任何成员之前应完成.

对于std::list和,有类似的措辞std::forward_list.

这个:

map<int, A> Am;
Run Code Online (Sandbox Code Playgroud)

是不正确的.std::map根据第一个引用,在实例化时需要一个完整的类型.这个容器没有例外vector.

这个:

pair<int, A> Ap;
Run Code Online (Sandbox Code Playgroud)

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


son*_*yao 5

[ 作为对巴里答案的补充说明 ]

根据标准(C ++ 17),只有std::vectorstd::list并且std::forward_list在实例化时可以与不完整类型一起使用。

§23.3.11.1/ 3类模板矢量概述[vector.overview]

T实例化vector分配器是否满足分配器完整性要求[allocator.requirements.completeness] 时,可以使用不完整类型。T必须先完成,然后再vector引用由此产生的专业化的任何成员。

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

T实例化forward_list分配器是否满足分配器完整性要求[allocator.requirements.completeness] 时,可以使用不完整类型。T必须先完成,然后再forward_list引用由此产生的专业化的任何成员。

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

T实例化list分配器是否满足分配器完整性要求[allocator.requirements.completeness] 时,可以使用不完整类型。T必须先完成,然后再list引用由此产生的专业化的任何成员。