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.
My question is that behavior dictated by the standard or specific to the compiler I am using?
A forward declaration tells the compiler about the existence of an entity before actually defining the entity. Forward declarations can also be used with other entity in C++, such as functions, variables and user-defined types.
In C/C++, Visual Assist can add a forward declaration for a referenced symbol, e.g. a pointer to a class, to make an unknown symbol known. The forward declaration, if sufficient, typically reduces compile time relative to a comparable include directive.
The relevant rules for the standard library types are in [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.
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. There is an explicit exception for this in the standard in [vector.overview]:
An incomplete type
Tmay be used when instantiatingvectorif the allocator satisfies the allocator completeness requirements 17.6.3.5.1.Tshall be complete before any member of the resulting specialization of vector is referenced.
There is similar wording for std::list and std::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. There is no exception for this container in the way that there is for vector.
This:
pair<int, A> Ap;
cannot possibly ever work, since pair is just a simply struct with two members. In order to have a member of type A, you need a complete type.
[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.
§23.3.11.1/3 Class template vector overview [vector.overview]:
An incomplete type
Tmay be used when instantiatingvectorif the allocator satisfies the allocator completeness requirements [allocator.requirements.completeness].Tshall be complete before any member of the resulting specialization ofvectoris referenced.
§23.3.9.1/4 Class template forward_list overview [forwardlist.overview]:
An incomplete type
Tmay be used when instantiatingforward_listif the allocator satisfies the allocator completeness requirements [allocator.requirements.completeness].Tshall be complete before any member of the resulting specialization offorward_listis referenced.
§23.3.10.1/3 Class template list overview [list.overview]:
An incomplete type
Tmay be used when instantiatinglistif the allocator satisfies the allocator completeness requirements [allocator.requirements.completeness].Tshall be complete before any member of the resulting specialization oflistis referenced.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With