Concepts / Container Characteristics in the STL

Container Characteristics in the STL

The label almost container is informal.

  • Programming

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?

  • No, because it is only a raw block of memory

  • Yes in a broad sense, because it holds elements, but it is an awkward fit for the STL

  • No, because only types named with the word container count as containers

Reveal answer
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

Definition

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.

FeatureAlmost containersTypical STL containers
Holds elementsYesYes
Shape compared with the typical patternDiffers through a restriction or an added facilityFollows the familiar pattern
Effect on the general description of the STLDescribed separately so the general rules stay simpleCovered directly by the general rules
Examples named in the sourceBuilt-in arrays, array, stringThe 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.

Ability to growGuaranteed fixedlocationElements do not moveon insertionContiguous allocationconflicts withconflicts with
Which requirements conflict, so that no single container can meet both members of a pair?

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.

SpecializedcontainersElement typeHeterogeneouspair, tupleAllocation styleHomogeneousall other containersAccess styleContiguousarray, vector, tupleLinkedforward_list, mapProxy accessbitset, vector boolDirect accessall other containerssort bysort bysort by
How do element type, allocation style, and access style divide the specialized containers?
ContainerElement typeAllocationAccess
arrayHomogeneousContiguousDirect
vectorHomogeneousContiguousDirect
tupleHeterogeneousContiguousDirect
pairHeterogeneousNot stated in sourceDirect
forward_listHomogeneousLinkedDirect
mapHomogeneousLinkedDirect
bitsetHomogeneousNot stated in sourceProxy objects
vector of boolHomogeneousNot stated in sourceProxy 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.

Mixed elementtypes?pair or tuplebitset or vector ofboolarray, vector, ortupleStoring bits?Contiguous allocationneeded?forward_list or mapyesnoyesnoyesno
Which sequence of questions leads from a stated need to a suitable container?
Worked example

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?

  1. 1
    Ask 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.

  2. 2
    Choose 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.

  3. 3
    Check 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.

Result

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 like

    Choosing a container only because it is the first one remembered, without asking what the need requires

    Why it fails

    The 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 instead

    Start from the need and apply the three classification questions before choosing.

  • Common mistake

    Assuming every container holds one type of element

    What it looks like

    Expecting a tuple to hold only values of a single type

    Why it fails

    Pair and tuple are heterogeneous, so their elements may be of different types. Only the other containers are homogeneous.

    Do this instead

    Ask 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 like

    Assuming built-in arrays, array, and string follow exactly the same rules as every other STL container

    Why it fails

    The source places these types in a separate group because each is shaped differently, usually through a restriction or an added facility.

    Do this instead

    Describe 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

EASY

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_list and 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.

Related concepts

More concepts starting with C