请考虑以下代码段,其中第一行仅用作前向声明
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上编译。
我的问题是标准或特定于我正在使用的编译器所指示的行为?
由于
答案 0 :(得分:11)
标准库类型的相关规则在[res.on.functions]中:
特别是,在以下情况下效果未定义:[...]如果在实例化模板组件时将不完整类型(3.9)用作模板参数,除非特别允许该组件。
此:
vector<A> Av;
很好。允许std::vector
实例化为不完整类型,只要它在您使用任何成员之前完成即可。在[vector.overview]的标准中有一个明确的例外:
如果分配器满足分配器完整性,则在实例化
T
时可以使用不完整类型vector
要求17.6.3.5.1。T
之前应在向量专业化的任何成员之前完成 被引用。
std::list
和std::forward_list
有类似的措辞。
此:
map<int, A> Am;
是不正确的。根据第一个引用,std::map
在实例化时需要一个完整的类型。这个容器没有例外vector
。
此:
pair<int, A> Ap;
不可能工作,因为pair
只是一个有两个成员的简单结构。要拥有A
类型的成员,您需要一个完整的类型。
答案 1 :(得分:5)
[作为Barry回答的补充说明]
根据标准(C ++ 17),实例化时,只有std::vector
,std::list
和std::forward_list
可用于不完整类型。
§23.3.11.1/3 Class template vector overview [vector.overview]:
如果分配器满足分配器完整性要求[allocator.requirements.completeness],则在实例化
T
时可以使用不完整类型vector
。在引用T
的结果专业化的任何成员之前,vector
应完成。
§23.3.9.1/4 Class template forward_list overview [forwardlist.overview]:
如果分配器满足分配器完整性要求[allocator.requirements.completeness],则在实例化
T
时可以使用不完整类型forward_list
。在引用T
的结果专业化的任何成员之前,forward_list
应完成。
§23.3.10.1/3 Class template list overview [list.overview]:
如果分配器满足分配器完整性要求[allocator.requirements.completeness],则在实例化
T
时可以使用不完整类型list
。在引用T
的结果专业化的任何成员之前,list
应完成。
答案 2 :(得分:2)
不,这种行为是预期和标准的。
理性是URLEmbeddedView实际上形成了一个结构,因此它们的类型必须在实例化之前完成。