使用STL容器前向声明对象
Forward declaration of objects with STL containers
考虑下面的代码片段,其中第一行仅用作前向声明
class A;
之后定义新的类
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]:
特别地,在下列情况下的效果是未定义的:[…]如果在实例化模板组件时使用不完整类型(3.9)作为模板参数,除非该组件特别允许。
:
vector<A> Av;
很好。允许使用不完整类型实例化std::vector
,只要它在使用任何成员之前变得完整即可。在[vector.overview]:
如果分配器满足分配器完整性,则在实例化
vector
时可以使用不完整类型T
17.6.3.5.1需求。T
应在产生的向量专门化的任何成员之前完成引用。
std::list
和std::forward_list
有类似的措辞。
:
map<int, A> Am;
是不规范的。std::map
在实例化时需要一个完整的类型,如第一个引号所示。这个容器不像vector
容器那样存在异常。
:
pair<int, A> Ap;
不可能工作,因为pair
只是一个具有两个成员的简单结构体。为了拥有类型A
的成员,您需要一个完整的类型。
[作为Barry回答的补充说明]
根据标准(c++ 17),实例化时只有std::vector
、std::list
和std::forward_list
可以使用不完全类型。
§23.3.11.1/3类模板向量概述[vector.overview]:
如果分配器满足分配器完整性要求,则在实例化
vector
时可以使用不完整类型T
[allocator.requirements.completeness]。T
应在引用vector
的任何结果专门化成员之前完成。
§23.3.9.1/4类模板forward_list概述[forwardlist.overview]:
如果分配器满足分配器完整性要求,则在实例化
forward_list
时可以使用不完整类型T
。T
必须在引用forward_list
的任何成员之前完成。
§23.3.10.1/3类模板列表概述[list.overview]:
在实例化
list
时,如果分配器满足分配器完整性要求[allocator.requirements.completeness],则可以使用不完整类型T
。T
应在引用list
的任何成员之前完成。
不,这种行为是预期的和标准的。
理由是std::pair实际上形成了一个结构体,因此在实例化之前它的两个类型都必须是完整的。
- Arduino C++在构造函数中用参数声明对象数组
- 为什么我在声明对象数组时不能使用 -> 运算符?
- 如何在 if 语句中声明对象并在任何我想的地方使用它?
- 如何使用unique_ptr和make_unique正确声明对象数组
- 声明对象时,如何在C 中修复C2065错误
- 声明对象而不调用默认构造函数
- 一旦对象设置为 null,用于声明对象的堆大小的变量就设置为 null?
- 我可以使用名称而不是类型来声明对象文字吗?
- 在制作(Qt等)GUI时声明对象
- 在基本的GUI编程中,在哪里声明对象和方法
- 同时使用模板和参数声明对象
- "Undefined reference to"使用双模板类声明对象时出错
- 在头文件 C++ 中声明对象
- 在其类中声明对象
- C 可以通过使用要求其为某个类别的对象来声明对象
- 声明对象
- (C++)如何基于条件声明对象类成员
- 使用变量声明对象的名称
- C++ OOP 体系结构:决定是从基类声明对象还是继承基类
- 在声明对象之前在全局函数中使用类的成员函数