10
10
11
11
<discussion >
12
12
<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.
29
28
</p >
30
29
</discussion >
31
30
@@ -56,8 +55,8 @@ template<class I>
56
55
</pre >
57
56
</blockquote >
58
57
<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
61
60
<tt >iter_difference_t< I> </tt >. The type `I` models `contiguous_iterator` only if
62
61
</p >
63
62
@@ -66,9 +65,9 @@ template<class I>
66
65
<li ><p >(2.2) — `to_address(b) == to_address(a) + D(b - a)`,</p ></li >
67
66
<li ><p >(2.3) — `to_address(c) == to_address(a) + D(c - a)`,</p ></li >
68
67
<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
70
69
`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
72
71
`ranges::swap(*a, *b)`.</p ></li >
73
72
</ol >
74
73
</blockquote >
0 commit comments