1010
1111<discussion >
1212<p >
13- The design intent of the `contiguous_iterator` concept is that iterators can be converted
14- to pointers that denote the same sequence of elements. Practically, that means that a common range
15- `[i, j)` or counted range `i + [0, n)` can be processed with extremely efficient
16- low-level C or assembly code that operates on `[to_address(i), to_address(j))` (respectively
17- `to_address(i) + [0, n)`). A value-initialized iterator `I{}` can be used to denote the empty
18- ranges `[I{}, I{})` and `I{} + [0, 0)`. While the existing semantic requirements of
19- `contiguous_iterator` enable us to convert both dereferenceable and past-the-end iterators with
20- `to_address` converting such ranges to pointer ranges requires either (1) `to_address(I{})`
21- is well-defined and equality preserving so e.g. `copy(i, j)` can directly dispatch to
22- `__vectorized_copy(to_address(j), to_address(i), j - i)` when it detects contiguous iterators
23- to types that can be trivially copied, or (2) we have to introduce a branch guarding such calls
24- with `i != j` (or <tt >n > 0</tt > for counted ranges).
25- <p />
26- Since we already require `to_address` to be equality-preserving, we need only require
27- `to_address(I{})` to be well-defined. It's then easily demonstrable that
28- `to_address(I{}) == to_address(I{})` and `to_address(I{}) == to_address(I{)) + 0` hold.
13+ The design intent of the `contiguous_iterator` concept is that iterators can be converted
14+ to pointers denoting the same sequence of elements. This enables a common range `[i, j)`
15+ or counted range `i + [0, n)` to be processed with extremely efficient low-level C
16+ or assembly code that operates on `[to_address(i), to_address(j))` (respectively
17+ `to_address(i) + [0, n)`).
18+ </p ><p >
19+ A value-initialized iterator `I{}` can be used to denote the empty ranges `[I{}, I{})`
20+ and `I{} + [0, 0)`. While the existing semantic requirements of `contiguous_iterator` enable us
21+ to convert both dereferenceable and past-the-end iterators with `to_address`, converting
22+ ranges involving value-initialized iterators to pointer ranges additionally needs
23+ `to_address(I{})` to be well-defined. Note that `to_address` is already implicitly
24+ equality-preserving for `contiguous_iterator` arguments. Given this additional requirement
25+ `to_address(I{}) == to_address(I{})` and `to_address(I{}) == to_address(I{)) + 0`
26+ both hold, so the two types of empty ranges involving value-initialized iterators convert
27+ to empty pointer ranges as desired.
2928</p >
3029</discussion >
3130
@@ -56,8 +55,8 @@ template<class I>
5655</pre >
5756</blockquote >
5857<p >
59- -2- Let `a` and `b` be dereferenceable iterators and `c` be a non-dereferenceable iterator of type
60- `I` such that `b` is reachable from `a` and `c` is reachable from `b`, and let `D` be
58+ -2- Let `a` and `b` be dereferenceable iterators and `c` be a non-dereferenceable iterator of type
59+ `I` such that `b` is reachable from `a` and `c` is reachable from `b`, and let `D` be
6160<tt >iter_difference_t< I> </tt >. The type `I` models `contiguous_iterator` only if
6261</p >
6362
@@ -66,9 +65,9 @@ template<class I>
6665<li ><p >(2.2) — `to_address(b) == to_address(a) + D(b - a)`,</p ></li >
6766<li ><p >(2.3) — `to_address(c) == to_address(a) + D(c - a)`,</p ></li >
6867<li ><p ><ins >(2.?) — `to_address(I{})` is well-defined,</ins ></p ></li >
69- <li ><p >(2.4) — `ranges::iter_move(a)` has the same type, value category, and effects as
68+ <li ><p >(2.4) — `ranges::iter_move(a)` has the same type, value category, and effects as
7069`std::move(*a)`, and</p ></li >
71- <li ><p >(2.5) — if `ranges::iter_swap(a, b)` is well-formed, it has effects equivalent to
70+ <li ><p >(2.5) — if `ranges::iter_swap(a, b)` is well-formed, it has effects equivalent to
7271`ranges::swap(*a, *b)`.</p ></li >
7372</ol >
7473</blockquote >
0 commit comments