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?
Thanks
[As supplemental instruction to Barry's answer]
According to the standard (C++17), only
std::vector
,std::list
andstd::forward_list
could be used with incomplete type when instantiating.§23.3.11.1/3 Class template vector overview [vector.overview]:
§23.3.9.1/4 Class template forward_list overview [forwardlist.overview]:
§23.3.10.1/3 Class template list overview [list.overview]:
The relevant rules for the standard library types are in [res.on.functions]:
This:
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]:There is similar wording for
std::list
andstd::forward_list
.This:
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 forvector
.This:
cannot possibly ever work, since
pair
is just a simply struct with two members. In order to have a member of typeA
, you need a complete type.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.