Iterator library
Iterators are a generalization of pointers that allow a C++ program to work with different data structures (for example, containers and ranges (since C++20)) in a uniform manner. The iterator library provides definitions for iterators, as well as iterator traits, adaptors, and utility functions.
Since iterators are an abstraction of pointers, their semantics are a generalization of most of the semantics of pointers in C++. This ensures that every function template that takes iterators works as well with regular pointers.
There are five(until C++17)six(since C++17) kinds of iterators: LegacyInputIterator, LegacyOutputIterator, LegacyForwardIterator, LegacyBidirectionalIterator, LegacyRandomAccessIterator , and LegacyContiguousIterator (since C++17). (See also LegacyIterator for the most basic kind of iterator.)
Instead of being defined by specific types, each category of iterator is defined by the operations that can be performed on it. This definition means that any type that supports the necessary operations can be used as an iterator -- for example, a pointer supports all of the operations required by LegacyRandomAccessIterator, so a pointer can be used anywhere a LegacyRandomAccessIterator is expected.
All of the iterator categories (except LegacyOutputIterator) can be organized into a hierarchy, where more powerful iterator categories (e.g. LegacyRandomAccessIterator) support the operations of less powerful categories (e.g. LegacyInputIterator). If an iterator falls into one of these categories and also satisfies the requirements of LegacyOutputIterator, then it is called a mutable iterator and supports both input and output. Non-mutable iterators are called constant iterators.
Iterators are called constexpr iterators if all operations provided to meet iterator category requirements are constexpr functions.
(since C++20)Iterator category | Operations and storage requirement | ||||||
---|---|---|---|---|---|---|---|
write | read | increment | decrement | random access |
contiguous storage | ||
without multiple passes |
with multiple passes | ||||||
LegacyIterator | Required | ||||||
LegacyOutputIterator | Required | Required | |||||
LegacyInputIterator (mutable if supports write operation) |
Required | Required | |||||
LegacyForwardIterator (also satisfies LegacyInputIterator) |
Required | Required | Required | ||||
LegacyBidirectionalIterator (also satisfies LegacyForwardIterator) |
Required | Required | Required | Required | |||
LegacyRandomAccessIterator (also satisfies LegacyBidirectionalIterator) |
Required | Required | Required | Required | Required | ||
LegacyContiguousIterator [1] (also satisfies LegacyRandomAccessIterator) |
Required | Required | Required | Required | Required | Required |
Note: A type supporting the required operations in a row of the table above does not necessarily fall into the corresponding category, see the category page for the complete list of requirements.
An input iterator i supports the expression *i, resulting in a value of some object type T
, called the value type of the iterator.
An output iterator i has a non-empty set of types that are writable(until C++20)indirectly_writable (since C++20) to the iterator; for each such type T
, the expression *i = o is valid where o is a value of type T
.
For every iterator type X
for which equality is defined(until C++20), there is a corresponding signed integer (until C++20)integer-like (since C++20) type called the difference type of the iterator.
Just as a regular pointer to an array guarantees that there is a pointer value pointing past the last element of the array, so for any iterator type there is an iterator value that points past the last element of a corresponding sequence. Such a value is called a past-the-end value.
Values of an iterator i for which the expression *i is defined are called dereferenceable. The standard library never assumes that past-the-end values are dereferenceable.
Iterators can also have singular values that are not associated with any sequence. Results of most expressions are undefined for singular values; the only exceptions are
In these cases the singular value is overwritten the same way as any other value. Dereferenceable values are always non-singular.
An invalid iterator is an iterator that may be singular.
Most of the standard library’s algorithmic templates that operate on data structures have interfaces that use ranges.
An iterator j is called reachable from an iterator i if and only if there is a finite sequence of applications of the expression ++i that makes i == j. If j is reachable from i, they refer to elements of the same sequence.
A range is a pair of iterators that designate the beginning and end of the computation. A range [
i,
i)
is an empty range; in general, a range [
i,
j)
refers to the elements in the data structure starting with the element pointed to by i and up to but not including the element pointed to by j.
Range [
i,
j)
is valid if and only if j is reachable from i.
A range can be denoted by either
[
i,
s)
, with an iterator i and a sentinel s that designate the beginning and end of the computation (i and s can have different types), or
+
[
0,
n)
, with an iterator i and a count n that designate the beginning and the number of elements to which the computation is to be applied.
An iterator and a sentinel denoting a range are comparable. [
i,
s)
is empty if i == s; otherwise, [
i,
s)
refers to the elements in the data structure starting with the element pointed to by i and up to but not including the element, if any, pointed to by the first iterator j such that j == s.
A sentinel s is called reachable from an iterator i if and only if there is a finite sequence of applications of the expression ++i that makes i == s.
If s is reachable from i, [
i,
s)
denotes a valid range.
A counted range i +
[
0,
n)
is empty if n == 0; otherwise, i +
[
0,
n)
refers to the n elements in the data structure starting with the element pointed to by i and up to but not including the element, if any, pointed to by the result of n applications of ++i.
A counted range i +
[
0,
n)
is valid if and only if
+
[
0,
--n)
is valid.
The result of the application of functions in the standard library to invalid ranges is undefined.
A new system of iterators based on concepts that are different from C++17 iterators. While the basic taxonomy remains similar, the requirements for individual iterator categories are somewhat different.
std
semiregular
type can be incremented with pre- and post-increment operators weakly_incrementable
type is equality-preserving and that the type is equality_comparable
input_iterator
is a forward iterator, supporting equality comparison and multi-pass forward_iterator
is a bidirectional iterator, supporting movement backwards bidirectional_iterator
is a random-access iterator, supporting advancement in constant time and subscripting random_access_iterator
is a contiguous iterator, referring to elements that are contiguous in memory
std
std::ranges
A set of concepts and related utility templates designed to ease constraining common algorithm operations.
<iterator>
std
indirectly_readable
type indirectly_readable
type, satisfies predicate
indirectly_readable
types, satisfies predicate
indirectly_readable
types, satisfies equivalence_relation
indirectly_readable
types, satisfies strict_weak_order
indirectly_readable
type to an indirectly_writable
type indirectly_readable
type to an indirectly_writable
type and that the move may be performed via an intermediate object indirectly_readable
type to an indirectly_writable
type indirectly_readable
type to an indirectly_writable
type and that the copy may be performed via an intermediate object indirectly_readable
types can be swapped indirectly_readable
types can be compared indirectly_readable
types<iterator>
These non-member function templates provide a generic interface for containers, plain arrays, and std::initializer_list .
<array>
<deque>
<flat_map>
<flat_set>
<forward_list>
<inplace_vector>
<iterator>
<list>
<map>
<regex>
<set>
<span>
<string>
<string_view>
<unordered_map>
<unordered_set>
<vector>
std
The following behavior-changing defect reports were applied retroactively to previously published C++ standards.
DR | Applied to | Behavior as published | Correct behavior |
---|---|---|---|
CWG 1181 | C++98 | array types could not be value types | they can |
LWG 208 | C++98 | past-the-end iterators were always non-singular | they can be singular |
LWG 278 | C++98 | the validity of an iterator was not defined | defined to be always non-singular |
LWG 324 | C++98 | output iterators had value types | output iterators have writable types instead |
LWG 407 | C++98 | singular iterators could not be destroyed | allowed |
LWG 408 (N3066) |
C++98 | singular iterators could not be copied | allowed if they are value-initialized |
LWG 1185 (N3066) |
C++98 | LegacyForwardIterator, LegacyBidirectionalIterator and LegacyRandomAccessIterator always satisfy LegacyOutputIterator |
they might not satisfy LegacyOutputIterator |
LWG 1210 (N3066) |
C++98 | the definition of iterator singularity and reachability depended on containers |
depend on sequences instead |
LWG 3009 | C++17 | <string_view> did not provide the range access function templates |
provides these templates |
LWG 3987 | C++23 | <flat_map> and <flat_set> did not provide the range access function templates |
provide these templates |