Almost any type can be used as the element type of a sequential container. In particular, we can define a container whose element type is itself another container. We define such containers exactly as we do any other container type: We specify the element type (which in this case is a container type) inside angle brackets:
vector<vector<string>> lines; // vector of vectors
Here lines
is a vector
whose elements are vectors
of string
s.
Older compilers may require a space between the angle brackets, for example, vector<vector<string> >
.
Although we can store almost any type in a container, some container operations impose requirements of their own on the element type. We can define a container for a type that does not support an operation-specific requirement, but we can use an operation only if the element type meets that operation’s requirements.
As an example, the sequential container constructor that takes a size argument (§ 3.3.1, p. 98) uses the element type’s default constructor. Some classes do not have a default constructor. We can define a container that holds objects of such types, but we cannot construct such containers using only an element count:
// assume noDefault is a type without a default constructor
vector<noDefault> v1(10, init); // ok: element initializer supplied
vector<noDefault> v2(10); // error: must supply an element initializer
As we describe the container operations, we’ll note the additional constraints, if any, that each container operation places on the element type.