Title
`contiguous_iterator` should require `to_address(I{})`
Status
voting
Section
[iterator.concept.contiguous]
Submitter
Casey Carter

Created on 2024-11-01.00:00:00 last changed yesterday

Messages

Date: 2024-11-13.20:38:33

Proposed resolution:

This wording is relative to N4993.

  1. Modify [iterator.concept.contiguous] as indicated:

    -1- The `contiguous_iterator` concept provides a guarantee that the denoted elements are stored contiguously in memory.

    template<class I>
      concept contiguous_iterator =
        random_access_iterator<I> &&
        derived_from<ITER_CONCEPT(I), contiguous_iterator_tag> &&
        is_lvalue_reference_v<iter_reference_t<I>> &&
        same_as<iter_value_t<I>, remove_cvref_t<iter_reference_t<I>>> &&
        requires(const I& i) {
          { to_address(i) } -> same_as<add_pointer_t<iter_reference_t<I>>>;
        };
    

    -2- Let `a` and `b` be dereferenceable iterators and `c` be a non-dereferenceable iterator of type `I` such that `b` is reachable from `a` and `c` is reachable from `b`, and let `D` be iter_difference_t<I>. The type `I` models `contiguous_iterator` only if

    1. (2.1) — `to_address(a) == addressof(*a)`,

    2. (2.2) — `to_address(b) == to_address(a) + D(b - a)`,

    3. (2.3) — `to_address(c) == to_address(a) + D(c - a)`,

    4. (2.?) — `to_address(I{})` is well-defined,

    5. (2.4) — `ranges::iter_move(a)` has the same type, value category, and effects as `std::move(*a)`, and

    6. (2.5) — if `ranges::iter_swap(a, b)` is well-formed, it has effects equivalent to `ranges::swap(*a, *b)`.

Date: 2024-11-15.00:00:00

[ 2024-11-13; Reflector poll ]

Set status to Tentatively Ready after eight votes in favour during reflector poll.

Date: 2024-11-01.16:14:17

The design intent of the `contiguous_iterator` concept is that iterators can be converted to pointers denoting the same sequence of elements. This enables a common range `[i, j)` or counted range `i + [0, n)` to be processed with extremely efficient low-level C or assembly code that operates on `[to_address(i), to_address(j))` (respectively `to_address(i) + [0, n)`).

A value-initialized iterator `I{}` can be used to denote the empty ranges `[I{}, I{})` and `I{} + [0, 0)`. While the existing semantic requirements of `contiguous_iterator` enable us to convert both dereferenceable and past-the-end iterators with `to_address`, converting ranges involving value-initialized iterators to pointer ranges additionally needs `to_address(I{})` to be well-defined. Note that `to_address` is already implicitly equality-preserving for `contiguous_iterator` arguments. Given this additional requirement `to_address(I{}) == to_address(I{})` and `to_address(I{}) == to_address(I{)) + 0` both hold, so the two types of empty ranges involving value-initialized iterators convert to empty pointer ranges as desired.

History
Date User Action Args
2024-11-19 16:09:07adminsetstatus: ready -> voting
2024-11-13 20:38:33adminsetmessages: + msg14452
2024-11-13 20:38:33adminsetstatus: new -> ready
2024-11-01 14:16:51adminsetmessages: + msg14447
2024-11-01 00:00:00admincreate