Title
subrange::advance(n) has UB when n < 0
Status
c++23
Section
[range.subrange.access]
Submitter
Casey Carter

Created on 2020-04-21.00:00:00 last changed 5 months ago

Messages

Date: 2021-02-26.17:31:29

Proposed resolution:

This wording is relative to N4861.

  1. Modify [range.subrange.access] as indicated:

    constexpr subrange& advance(iter_difference_t<I> n);
    

    -9- Effects: Equivalent to:

    1. (9.1) — If StoreSize is true,

      auto d = n - ranges::advance(begin_, n, end_);
      if (d >= 0)
        size_ -= to-unsigned-like(d);
      else
        size_ += to-unsigned-like(-d);
      return *this;
      
    2. (9.2) — Otherwise,

      ranges::advance(begin_, n, end_);
      return *this;
      
    if constexpr (bidirectional_iterator<I>) {
      if (n < 0) {
        ranges::advance(begin_, n);
        if constexpr (StoreSize)
          size_ += to-unsigned-like(-n);
        return *this;
      }
    }
    
    auto d = n - ranges::advance(begin_, n, end_);
    if constexpr (StoreSize)
      size_ -= to-unsigned-like(d);
    return *this;
    

Date: 2021-02-26.00:00:00

[ 2021-02-26 Approved at February 2021 virtual plenary. Status changed: Tentatively Ready → WP. ]

Date: 2021-01-15.00:00:00

[ 2021-01-15; Issue processing telecon ]

Set status to Tentatively Ready after discussion and poll.

FAN
703

Date: 2020-05-15.00:00:00

[ 2020-05-11; Reflector prioritization ]

Set priority to 2 after reflector discussions.

Date: 2020-04-21.00:00:00

subrange::advance(n) is specified to call ranges::advance(begin_, n, end_) in both StoreSize and !StoreSize cases ([range.subrange.access]/9). Unfortunately, ranges::advance(begin_, n, end_) has undefined behavior when n < 0 unless [end_, begin_) denotes a valid range ([range.iter.op.advance]/5). This would all be perfectly fine — the UB is exposed to the caller via effects-equivalent-to — were it not the design intent that subrange::advance(-n) be usable to reverse the effects of subrange::advance(n) when the subrange has a bidirectional iterator type. That is, however, clearly the design intent: subrange::prev(), for example, is equivalent to subrange::advance(-1).

History
Date User Action Args
2023-11-22 15:47:43adminsetstatus: wp -> c++23
2021-02-26 17:31:29adminsetmessages: + msg11700
2021-02-26 17:31:29adminsetstatus: ready -> wp
2021-01-15 22:03:31adminsetmessages: + msg11655
2021-01-15 22:03:31adminsetstatus: new -> ready
2020-05-11 15:19:14adminsetmessages: + msg11288
2020-04-25 11:51:57adminsetmessages: + msg11235
2020-04-21 00:00:00admincreate