Title
ranges::advance violates its preconditions
Status
c++23
Section
[range.iter.op.advance]
Submitter
Casey Carter

Created on 2019-10-27.00:00:00 last changed 13 months ago

Messages

Date: 2020-11-09.21:40:50

Proposed resolution:

This wording is relative to N4835.

  1. Modify [range.iter.op.advance] as indicated:

    template<input_or_output_iterator I, sentinel_for<I> S>
      constexpr void ranges::advance(I& i, S bound);
    

    -3- Expects: Either assignable_from<I&, S> || sized_sentinel_for<S, I> is modeled, or [i, bound) denotes a range.

    -4- Effects:

    (4.1) — If I and S model assignable_from<I&, S>, equivalent to i = std::move(bound).

    (4.2) — Otherwise, if S and I model sized_sentinel_for<S, I>, equivalent to ranges::advance(i, bound - i).

    (4.3) — Otherwise, while bool(i != bound) is true, increments i.

Date: 2020-11-09.00:00:00

[ 2020-11-09 Approved In November virtual meeting. Status changed: Tentatively Ready → WP. ]

Date: 2020-08-21.00:00:00

[ 2020-08-21 Issue processing telecon: moved to Tentatively Ready ]

Date: 2019-11-04.13:23:43

[ 2019-11 Priority to 2 during Monday issue prioritization in Belfast ]

Date: 2019-10-27.00:00:00

Recall that "[i, s) denotes a range" for an iterator i and sentinel s means that either i == s holds, or i is dereferenceable and [++i, s) denotes a range ([iterator.requirements.general).

The three-argument overload ranges::advance(i, n, bound) is specified in [range.iter.op.advance] paragraphs 5 through 7. Para 5 establishes a precondition that [bound, i) denotes a range when n < 0 (both bound and i must have the same type in this case). When sized_sentinel_for<S, I> holds and n < bound - i, para 6.1.1 says that ranges::advance(i, n, bound) is equivalent to ranges::advance(i, bound). Para 3, however, establishes a precondition for ranges::advance(i, bound) that [i, bound) denotes a range. [bound, i) and [i, bound) cannot both denote ranges unless i == bound, which is not the case for all calls that reach 6.1.1.

The call in para 6.1.1 wants the effects of either 4.1 - which really has no preconditions - or 4.2, which is well-defined if either [i, bound) or [bound, i) denotes a range. Para 3's stronger precondition is actually only required by Para 4.3, which increments i blindly looking for bound. The straight-forward fix here seems to be to relax para 3's precondition to only apply when 4.3 will be reached.

History
Date User Action Args
2023-11-22 15:47:43adminsetstatus: wp -> c++23
2020-11-09 21:40:50adminsetmessages: + msg11558
2020-11-09 21:40:50adminsetstatus: ready -> wp
2020-08-21 20:59:51adminsetmessages: + msg11455
2020-08-21 20:59:51adminsetstatus: new -> ready
2019-11-04 13:23:43adminsetmessages: + msg10726
2019-10-27 06:54:18adminsetmessages: + msg10709
2019-10-27 00:00:00admincreate