Container Characteristics in the STL
The label almost container is informal.
A Container That Is Not Quite a Container
Most of the standard library's containers follow one familiar pattern: they hold elements and give you a common way to work with them. You learn the pattern once and it applies across many types. But some types in the library hold elements too, and yet they do not fit that pattern cleanly. This article is about those types and about the larger question they raise: why does the library offer so many containers in the first place, and how do you choose among them?
What do you think happens?
Before reading on: is a built-in array a container in the STL sense?
Reveal answer
Yes in a broad sense, because it holds elements, but it is an awkward fit for the STL
A type that holds elements is a container by that broad definition. The source calls such types almost containers when they carry a restriction or an added facility that makes them awkward to treat in the same way as the rest of the STL.
What Makes a Container Almost
An almost container is a type that holds elements and is therefore a container, but that has restrictions or added facilities making it awkward within the STL.
The key phrase is 'holds elements and is therefore a container.' Membership in the group does not depend on whether a type is useful or famous. It depends on two things together. First, the type stores a collection of elements. Second, it is shaped differently from the typical STL container, usually because of a restriction it places on how it can be used or because of an extra facility it adds. The difference is what makes it 'almost' a container rather than a full one.
The Three Almost Containers
The source names three examples: built-in arrays, the array type, and the string type. Each holds elements, and each is shaped differently from a typical STL container. Built-in arrays are the arrays that come with the core language rather than with the library. The array type is a library type for holding a sequence of elements. The string type holds characters. Listing them under one label lets the description of the STL itself stay simpler, because the general rules of the framework do not have to absorb every exception.
| Feature | Almost containers | Typical STL containers |
|---|---|---|
| Holds elements | Yes | Yes |
| Shape compared with the typical pattern | Differs through a restriction or an added facility | Follows the familiar pattern |
| Effect on the general description of the STL | Described separately so the general rules stay simple | Covered directly by the general rules |
| Examples named in the source | Built-in arrays, array, string | The remaining standard containers |
Almost containers and typical STL containers both hold elements. The difference lies in shape, not in whether they store things.
Why the Library Offers So Many Containers
A natural question follows from the list of almost containers: why does the standard library provide so many containers at all? The source's answer is that they serve common needs. Those needs are common to many programmers, but they differ from one another, and they often overlap. If the library did not supply these containers, many programmers would have to design and implement their own versions of the same structures.
The reason one container cannot cover every need is that some needs contradict each other. The source gives two pairs of conflicting requirements. The first pair is the ability to grow, set against being guaranteed to be allocated in a fixed location. The second pair is elements not moving when new elements are added, set against elements being contiguously allocated. A single general-purpose container that satisfies both members of either pair is not possible. The diagram below lays out these conflicts.
There is a second reason as well, and it concerns cost rather than possibility. A very general container would carry overhead that is unacceptable for many individual uses. Specialized containers exist so that each one can provide the services a particular group of programmers needs, without paying for services it does not need. Read this way, the variety of containers is a design choice that trades one general tool for several focused ones.
Classifying Specialized Containers
The source describes the specialized containers as providing services needed by large communities of programmers. Rather than memorizing them as a flat list, it helps to sort them by three characteristics: the kind of elements they hold, how those elements are allocated in memory, and how elements are accessed. The concept map below shows how these three axes divide the specialized containers. After it, each axis is explained in turn.
| Container | Element type | Allocation | Access |
|---|---|---|---|
| array | Homogeneous | Contiguous | Direct |
| vector | Homogeneous | Contiguous | Direct |
| tuple | Heterogeneous | Contiguous | Direct |
| pair | Heterogeneous | Not stated in source | Direct |
| forward_list | Homogeneous | Linked | Direct |
| map | Homogeneous | Linked | Direct |
| bitset | Homogeneous | Not stated in source | Proxy objects |
| vector of bool | Homogeneous | Not stated in source | Proxy objects |
Each specialized container placed on the three axes. Where the source does not state an allocation style, the table says so rather than guessing.
Choosing a Container for a Stated Need
The classification is most useful when it is applied to a concrete need. The flowchart below turns the three questions into a sequence: first ask about element types, then about bits, then about allocation. The scenario that follows is an original illustration built on the characteristics in the table, not an example taken from the source.
Storing a Name Together With a Score
A program needs to keep one student's name and one numeric score together as a single unit. Which container category fits, and why?
- 1Ask the element type question
The name and the score are different kinds of values, so the elements are not all of one type. That makes the need heterogeneous.
- 2Choose from the heterogeneous containers
According to the classification, pair and tuple are the heterogeneous containers. A pair is the natural fit for exactly two values, which is this case.
- 3Check the allocation and access questions
The need does not involve storing bits, so the proxy-access containers do not apply. The allocation question does not change the answer here because the need is only to group two values.
A pair fits the stated need. The heterogeneous branch of the classification leads to pair or tuple, and a pair holds exactly two elements of possibly different types.
Mistakes When Classifying Containers
Common mistake Treating all containers as interchangeable
What it looks likeChoosing a container only because it is the first one remembered, without asking what the need requires
Why it failsThe source explains that some needs contradict each other, so no single container can serve every need. The variety exists because the trade-offs really differ.
Do this insteadStart from the need and apply the three classification questions before choosing.
Common mistake Assuming every container holds one type of element
What it looks likeExpecting a tuple to hold only values of a single type
Why it failsPair and tuple are heterogeneous, so their elements may be of different types. Only the other containers are homogeneous.
Do this insteadAsk first whether the need involves mixed element types, because that question separates pair and tuple from the rest.
Common mistake Calling an almost container a full container
What it looks likeAssuming built-in arrays, array, and string follow exactly the same rules as every other STL container
Why it failsThe source places these types in a separate group because each is shaped differently, usually through a restriction or an added facility.
Do this insteadDescribe built-in arrays, array, and string as almost containers and check their specific restrictions before relying on general STL rules.
Common mistake Assuming the proxy-access containers hand back plain stored values in the same way as direct-access containers
Practice Sorting a New Need
A program must store eight independent on or off flags for a device, and each flag is a single bit. Using the three questions from the classification, decide which container category applies and state which sorting question settled it.
Hints
- Start with the element type question. Are the flags of mixed types, or are they all the same kind of thing?
- Then ask whether the need is about storing bits. The source names bitset and vector of bool as the containers that hold bits.
- Note which access style applies to those containers.
Key Takeaways
- An almost container holds elements and is therefore a container, but it has restrictions or added facilities that make it awkward within the STL. The source names built-in arrays, array, and string.
- The standard library offers many containers because common needs differ and overlap, and some needs contradict each other, so one container cannot serve them all.
- Specialized containers can be classified by element type (pair and tuple are heterogeneous, the rest homogeneous), allocation style (array, vector, and tuple are contiguous;
forward_listand map are linked), and access style (bitset and vector of bool use proxy objects). - To choose a container, ask the classification questions in order, starting with whether the element types are mixed.