Title
std::ranges::iota_view<int, long> has non-subtractable iterator and sentinel types
Status
new
Section
[range.iota.sentinel]
Submitter
Jiang An

Created on 2021-09-25.00:00:00 last changed 37 months ago

Messages

Date: 2021-10-14.11:35:36

Proposed resolution:

This wording is relative to N4892.

  1. Modify [range.iota.sentinel] as indicated:

    namespace std::ranges {
      template<weakly_incrementable W, semiregular Bound>
        requires weakly-equality-comparable-with<W, Bound> && copyable<W>
      struct iota_view<W, Bound>::sentinel {
      private:
        Bound bound_ = Bound(); // exposition only
      public:
        sentinel() = default;
        constexpr explicit sentinel(Bound bound);
        
        friend constexpr bool operator==(const iterator& x, const sentinel& y);
        
        friend constexpr iter_difference_t<W>IOTA-DIFF-T(W) operator-(const iterator& x, const sentinel& y)
          requires (is-integer-like<W> && is-integer-like<Bound>) || sized_sentinel_for<Bound, W>;
    
        friend constexpr iter_difference_t<W>IOTA-DIFF-T(W) operator-(const sentinel& x, const iterator& y)
          requires (is-integer-like<W> && is-integer-like<Bound>) || sized_sentinel_for<Bound, W>;
      };
    }
    

    […]

    friend constexpr iter_difference_t<W>IOTA-DIFF-T(W) operator-(const iterator& x, const sentinel& y)
      requires (is-integer-like<W> && is-integer-like<Bound>) || sized_sentinel_for<Bound, W>;
    

    -3- Effects: Equivalent to: return x.value_ - y.bound_;

    using D = IOTA-DIFF-T(W);
    if constexpr (is-integer-like<W>) {
      auto y_value = W(y.bound_);
      if constexpr (is-signed-integer-like<W>) {
        return D(D(x.value_) - D(y_value));
      } else {
        return (y_value > x.value_)
          ? D(-D(y_value - x.value_))
          : D(x.value_ - y_value);
      }
    } else {
      return x.value_ - y.bound_;
    }
    
    friend constexpr iter_difference_t<W>IOTA-DIFF-T(W) operator-(const sentinel& x, const iterator& y)
      requires (is-integer-like<W> && is-integer-like<Bound>) || sized_sentinel_for<Bound, W>;
    

    -4- Effects: Equivalent to: return -(y - x);

Date: 2021-10-14.11:35:36

[ Tim Song commented: ]

We might be able to simplify the (y_value > x.value_) conditional since we know that we are working with an iterator and its sentinel.

Date: 2021-10-15.00:00:00

[ 2021-10-14; Reflector poll ]

Set priority to 3 after reflector poll.

Date: 2021-09-25.00:00:00

Currently std::ranges::iota_view<int, long> uses its special sentinel type, as its W and Bound are different types and Bound is not std::unreachable_sentinel_t. However, as W (int) is not an iterator type, the iterator and sentinel types don't satisfy std::sized_sentinel_for, and thus not subtractable.

IMO we should handle operator- overloads for iota_view::iterator and iota_view::sentinel like iota_view::size and operator- for iota_view::iterator.

History
Date User Action Args
2021-10-14 11:35:36adminsetmessages: + msg12166
2021-10-14 11:35:36adminsetmessages: + msg12165
2021-10-03 13:04:09adminsetmessages: + msg12090
2021-09-25 00:00:00admincreate