Issue 4170: contiguous_iterator should require to_address(I{}) (original) (raw)


This page is a snapshot from the LWG issues list, see the Library Active Issues List for more information and the meaning of WP status.

4170. contiguous_iterator should require to_address(I{})

Section: 24.3.4.14 [iterator.concept.contiguous] Status: WP Submitter: Casey Carter Opened: 2024-11-01 Last modified: 2024-11-28

Priority: Not Prioritized

View all other issues in [iterator.concept.contiguous].

View all issues with WP status.

Discussion:

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)) (respectivelyto_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 needsto_address(I{}) to be well-defined. Note that to_address is already implicitly equality-preserving for contiguous_iterator arguments. Given this additional requirementto_address(I{}) == to_address(I{}) and to_address(I{}) == to_address(I{)) + 0both hold, so the two types of empty ranges involving value-initialized iterators convert to empty pointer ranges as desired.

[2024-11-13; Reflector poll]

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

[Wrocław 2024-11-23; Status changed: Voting → WP.]

Proposed resolution:

This wording is relative to N4993.

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

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

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

};

-2- Let a and b be dereferenceable iterators and c be a non-dereferenceable iterator of typeI such that b is reachable from a and c is reachable from b, and let D beiter_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 asstd::move(*a), and
  6. (2.5) — if ranges::iter_swap(a, b) is well-formed, it has effects equivalent toranges::swap(*a, *b).