I think the relevant part of the C++17
Standard is here
27.2.1 In general [ iterator.requirements.general ]
...
8 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.
9 Most of the library’s algorithmic templates that operate on data structures have interfaces that use ranges. 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
. The result of the application of functions in the library to invalid ranges is undefined.
So extracting the pertinent parts:
8 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
...
9 ... Range [i, j)
is valid if and only if j
is reachable from i
....
So it seems that a "valid range" is a pair of iterators that belong to the same container (or array), with j
being farther along than i
.
But also not forgetting:
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
.
So all of the iterators between i
and j
(but not necessarily including j
) must be "in the data structure" (ie. not out-of-bounds).