Concepts / Sequences and Iterators in the Standard Library

Sequences and Iterators in the Standard Library

The std namespace algorithms take a pair of positions as the sequence. The Estd namespace holds container versions that accept a whole container and are a convenience over the same sequence idea.

  • Programming

Testing an Intuition About Algorithms

When you first meet the standard library's algorithms, it is natural to assume they behave like methods on the container they touch. If an algorithm is handed a container, you might expect it to be able to shrink it, grow it, or rearrange everything inside it. That expectation comes from experience: most people first learn containers through operations that visibly change them, such as adding an item to the end of a list or removing one from the middle.

The source material corrects this belief directly. Standard library algorithms can change the values of the elements they work on, but no algorithm adds or subtracts elements of a container. As you read the rest of this article, keep that line in mind and test it on the operations you already know.

What do you think happens?

Does calling an algorithm such as sort() on a container change how many elements the container holds?

  • Yes, sort() can add or remove elements to keep the container ordered

  • No, sort() changes only the values of existing elements

Reveal answer
Answer:

No, sort() changes only the values of existing elements.

The source states that algorithms can change element values, such as with replace() and sort(), but no algorithm adds or subtracts elements of a container. Changing the number of elements requires container operations.

Algorithms as Reusable Operations

The standard library provides dozens of algorithms. They are defined in the namespace std and presented in the algorithm header. Each one is a reusable operation that either answers a question about a group of elements or performs a transformation on that group. Instead of writing a loop by hand over the same group, you should prefer the standard algorithm, because the standard library's algorithms tend to be more carefully designed, specified, and implemented than the average loop written from scratch.

Definition

A standard library algorithm is a reusable operation, declared in the namespace std and presented in the algorithm header, that receives its input as a sequence and answers a question about those elements or transforms them.

The source lists a representative set of algorithms, and each follows the same pattern. A sequence is supplied as input, and the algorithm works over the elements in that range. Find returns the position of the first element in the sequence that matches a value, or the end position if none does. Count returns how many elements in the sequence equal a value. Replace changes every matching element in the sequence to a new value. Find_if, count_if, and replace_if do the same jobs but use a test function instead of a fixed value to decide which elements qualify.

Other algorithms copy elements to an output position, move them, remove adjacent duplicates while copying, sort the elements, return the subsequence of equal values in a sorted sequence, or merge two sorted sequences into one output. The source notes that these algorithms, and many more, can be applied to the elements of containers, to strings, and to built-in arrays.

Reading a Half-Open Range

Every standard library algorithm receives its input as a sequence, and a sequence is described by two positions. The first marks where the sequence starts and the second marks where it ends. The source writes a half-open sequence from b to e as $[b : e)$. The square bracket on the left means the start position is included. The parenthesis on the right means the end position is excluded. So the sequence covers the elements from b up to, but not including, e.

v[0]value 10v[1] = bvalue 20, includedv[2]value 30, includedv[3]value 40, includedv[4] = eend, not includednextnextnext
With b at position 1 and e at position 4, the range $[b : e)$ covers positions 1, 2, and 3. Position 4 marks the end and is not part of the range.
Worked example

Finding which elements a range covers

A container holds the values 10, 20, 30, 40, 50 at positions 0 through 4. An algorithm is given the sequence $[b : e)$ where b is position 1 and e is position 4. Which elements does the algorithm read?

  1. 1
    Locate the start

    The start position b is position 1, which holds 20. The start is included, so 20 is in the sequence.

  2. 2
    Walk forward

    Move one position at a time. Position 2 holds 30 and position 3 holds 40. Both lie before e, so both are included.

  3. 3
    Stop at the end

    Position 4 is e. The end is excluded, so the value 50 is not part of the sequence even though it sits in the container.

  4. 4
    Count the elements

    The number of elements is the distance between the two positions, 4 minus 1, which is 3.

Result

The sequence covers the values 20, 30, and 40. The value 50 is outside the range.

The excluded end position is not an accident of notation. It is what allows the end position to act as a stopping marker. An algorithm that searches a sequence and finds nothing has nowhere to point inside the range, so the conventional result is the end position itself. The same convention makes empty ranges simple: when the two positions are equal, the sequence has zero elements and no special case is needed.

Why Algorithms Cannot Change Size

The rule that algorithms never add or subtract elements follows from how sequences are defined. A sequence is given by two positions and nothing else. The algorithm therefore sees a run of elements that it can read and, where the operation calls for it, overwrite. Overwriting a value is possible because each position leads to an element that can be assigned to.

What the algorithm never sees is the container that owns those elements. It has no handle through which to insert a new element or erase an old one. Changing how many elements exist therefore requires operating on the container itself. The diagram of this relationship has no edge leading from the algorithm back to the container, and that missing link is exactly why an algorithm alone cannot change the element count.

replaceoverwrites matching valuespush_back()adds at the endsortreorders valueserase()removes an elementback inserteroutput connected tocontainer
Replace and sort change values inside the existing sequence. Push_back, erase, and a back inserter are the routes that change how many elements the container holds.

Sort and replace belong to the first column. Although sort() reorders the elements and replace() overwrites matching ones, each keeps the same set of positions and the same count. The second column contains the routes that bring the container into the work. A back inserter is special because it is a connection to the container, which lets an algorithm that writes to an output position add elements to that container.

Adding and Removing Through the Container

If elements must be added or removed, the source gives two routes. One is to supply something that knows about the container, such as a back inserter, so that an algorithm writing to an output position can add elements to the container it is connected to. The other is to call operations directly on the container, such as push_back() to add an element at the end or erase() to remove one. Both routes bring the container into the work, which the bare algorithm does not do.

The before and after states above show the key point. A replace operation over the sequence changes the middle value from 8 to 5, but the container still holds three elements. Nothing about the algorithm's run could have removed or added a slot. If the program needs the container to hold a different number of elements, it must call a container operation such as erase() or push_back() in addition to any algorithm it uses.

Where Container Versions Live

Most of the time an algorithm is applied to a sequence that is the contents of a container. The source notes that the sequence concept is general and flexible, but in practice the sequence usually comes from a container. To make that common case easier, container versions of sort() and other algorithms can be provided. The source places these container versions in their own namespace, called Estd, which stands for extended std.

The separation exists to avoid interfering with other programmers' uses of namespace std. Keeping the container versions apart means a program can use a shorthand that accepts a whole container while the standard namespace keeps its original, sequence-based meaning. The shorthand is a convenience layer built on the same underlying idea of a sequence defined by a pair of positions.

Key point

The std namespace algorithms take a pair of positions as the sequence. The Estd namespace holds container versions that accept a whole container and are a convenience over the same sequence idea.

Mistakes Learners Make with Sequences

  • Common mistake

    Assuming an algorithm will shrink or grow the container it reads

    What it looks like

    Calling replace() on a three-element container and expecting it to hold fewer elements afterward.

    Why it fails

    No algorithm adds or subtracts elements of a container. The algorithm only sees a sequence defined by two positions and has no handle on the container.

    Do this instead

    Use container operations such as erase() or push_back(), or an inserter connected to the container, when the count must change.

  • Common mistake

    Including the end position in the range

    What it looks like

    Reading $[b : e)$ as if e were the last element included, so that the range above would be taken to hold four values instead of three.

    Why it fails

    The square bracket includes b but the parenthesis excludes e.

    Do this instead

    Count the elements as the distance from b to e. Stop before e, not at it.

  • Common mistake

    Treating the end position as a real element

    Why it fails

    The end position is a stopping marker. An algorithm that finds nothing returns it, so it does not hold a value to read.

    Do this instead

    Compare results against the end position to detect that nothing matched, and never dereference it as a value.

  • Common mistake

    Looking for the container versions in the std namespace

    Why it fails

    The std namespace keeps the sequence-based meaning of the algorithms. The container shorthand lives separately.

    Do this instead

    Look for container versions in the Estd namespace, which stands for extended std.

Practice Reading Ranges

MEDIUM

A container holds the values 5, 9, 1, 7, 3 at positions 0 through 4. An algorithm is given the sequence $[b : e)$ with b at position 2 and e at position 5. List the values the algorithm reads. Then decide whether a replace() call on this sequence could change how many elements the container holds.

Hints
  • Count from b upward and stop just before e.
  • Position 5 is one past the last element, so it is excluded.
  • Algorithms change values, not the number of elements.

Recap of the Sequence Model

  • Standard library algorithms are declared in namespace std, presented in the algorithm header, and take sequences as their inputs.
  • A half-open sequence $[b : e)$ includes b and excludes e, and is described only by that pair of positions.
  • Algorithms can change element values but never add or subtract elements of a container.
  • Changing the number of elements requires container operations such as push_back() and erase(), or an inserter connected to the container.
  • Container versions of algorithms live in the Estd namespace, which keeps the sequence-based meaning of std intact.

Key Takeaways

  • Standard library algorithms are declared in namespace std, presented in the algorithm header, and take sequences as their inputs.
  • A half-open sequence $[b : e)$ covers the elements from b up to but not including e, and its size is the distance between the two positions.
  • Algorithms can change element values, but no algorithm adds or subtracts elements; changing the count needs container operations or an inserter.
  • Container versions of algorithms are placed in the Estd namespace, which avoids interfering with the sequence-based meaning of std.

Related concepts

More concepts starting with S