简体   繁体   English

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

[英]Forward declaration of objects with STL containers

Consider the following code snippet, where the first line serves only as forward declaration 请考虑以下代码段,其中第一行仅用作前向声明

 class A;

followed by defining new class 然后定义新类

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

line 1 and line 2 seems to be fine with the forward declaration (which may tell me that those container use pointer type of implementation) where as line 3 does not seem to compile on VS2012. 第1行和第2行似乎没有前向声明(这可能告诉我那些容器使用指针类型的实现),其中第3行似乎不在VS2012上编译。

My question is that behavior dictated by the standard or specific to the compiler I am using? 我的问题是标准或特定于我正在使用的编译器所规定的行为?

Thanks 谢谢

The relevant rules for the standard library types are in [res.on.functions]: 标准库类型的相关规则在[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. 特别是,在以下情况下,效果未定义:[...]如果在实例化模板组件时将不完整类型(3.9)用作模板参数,除非特别允许该组件。

This: 这个:

vector<A> Av;

is fine. 很好。 std::vector is allowed to be instantiated with an incomplete type, as long as it becomes complete before you use any of the members. 允许std::vector使用不完整类型进行实例化,只要它在您使用任何成员之前完成即可。 There is an explicit exception for this in the standard in [vector.overview]: 在[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. 如果分配器满足分配器完整性要求17.6.3.5.1,则在实例化vector时可以使用不完整类型T T shall be complete before any member of the resulting specialization of vector is referenced. 在引用向量特化的任何成员之前, T应该是完整的。

There is similar wording for std::list and std::forward_list . 对于std::liststd::forward_list有类似的措辞。

This: 这个:

map<int, A> Am;

is ill-formed. 是不正确的。 std::map requires a complete type at point of instantiation as per the first quote. 根据第一个引用, std::map在实例化时需要一个完整的类型。 There is no exception for this container in the way that there is for vector . 这个容器没有例外,就像vector

This: 这个:

pair<int, A> Ap;

cannot possibly ever work, since pair is just a simply struct with two members. 不可能工作,因为pair只是一个有两个成员的简单结构。 In order to have a member of type A , you need a complete type. 要拥有A类成员,您需要一个完整的类型。

[ As supplemental instruction to Barry's answer ] [ 作为对巴里答案的补充指导 ]

According to the standard (C++17), only std::vector , std::list and std::forward_list could be used with incomplete type when instantiating. 根据标准(C ++ 17),在实例化时,只有std::vectorstd::liststd::forward_list可以与不完整类型一起使用。

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

An incomplete type T may be used when instantiating vector if the allocator satisfies the allocator completeness requirements [allocator.requirements.completeness]. 如果分配器满足分配器完整性要求[allocator.requirements.completeness],则在实例化vector时可以使用不完整类型T T shall be complete before any member of the resulting specialization of vector is referenced. 在引用vector任何成员之前, T应该是完整的。

§23.3.9.1/4 Class template forward_list overview [forwardlist.overview] : §23.3.9.1/ 4类模板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]. 如果分配器满足分配器完整性要求[allocator.requirements.completeness],则在实例化forward_list时可以使用不完整类型T T shall be complete before any member of the resulting specialization of forward_list is referenced. 在引用forward_list成员的任何成员之前, T应该完成。

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

An incomplete type T may be used when instantiating list if the allocator satisfies the allocator completeness requirements [allocator.requirements.completeness]. 如果分配器满足分配器完整性要求[allocator.requirements.completeness],则在实例化list时可以使用不完整类型T T shall be complete before any member of the resulting specialization of list is referenced. 在引用list专有化的任何成员之前, T应该是完整的。

Nope, this behavior is expected and standard. 不,这种行为是预期的和标准的。

The rational is that std::pair actually forms a struct, therefore both its types must be complete before instantiation. 理性的是std :: pair实际上形成了一个结构,因此它的类型必须在实例化之前完成。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM