使用 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::list
和 std::forward_list
有相似的措辞。
这个:
map<int, A> Am;
格式错误。 std::map
根据第一个引号,在实例化时需要一个完整的类型。对于 vector
.
的方式,此容器也不例外
这个:
pair<int, A> Ap;
不可能工作,因为 pair
只是一个有两个成员的简单结构。为了拥有 A
类型的成员,您需要一个完整的类型。
不,这种行为是预期的和标准的。
合理的是std::pair实际上形成了一个结构体,因此在实例化之前它的两个类型必须是完整的。
[作为 Barry 回答的补充说明]
根据标准(C++17),在实例化时只有std::vector
、std::list
和std::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.
考虑以下代码片段,其中第一行仅用作前向声明
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 instantiatingvector
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::list
和 std::forward_list
有相似的措辞。
这个:
map<int, A> Am;
格式错误。 std::map
根据第一个引号,在实例化时需要一个完整的类型。对于 vector
.
这个:
pair<int, A> Ap;
不可能工作,因为 pair
只是一个有两个成员的简单结构。为了拥有 A
类型的成员,您需要一个完整的类型。
不,这种行为是预期的和标准的。
合理的是std::pair实际上形成了一个结构体,因此在实例化之前它的两个类型必须是完整的。
[作为 Barry 回答的补充说明]
根据标准(C++17),在实例化时只有std::vector
、std::list
和std::forward_list
可以使用不完整的类型。
§23.3.11.1/3 Class 模板向量概述 [vector.overview]:
An incomplete type
T
may be used when instantiatingvector
if the allocator satisfies the allocator completeness requirements [allocator.requirements.completeness].T
shall be complete before any member of the resulting specialization ofvector
is referenced.
§23.3.9.1/4 Class 模板 forward_list 概述 [forwardlist.overview]:
An incomplete type
T
may be used when instantiatingforward_list
if the allocator satisfies the allocator completeness requirements [allocator.requirements.completeness].T
shall be complete before any member of the resulting specialization offorward_list
is referenced.
§23.3.10.1/3 Class 模板列表概述 [list.overview]:
An incomplete type
T
may be used when instantiatinglist
if the allocator satisfies the allocator completeness requirements [allocator.requirements.completeness].T
shall be complete before any member of the resulting specialization oflist
is referenced.