Title
take_view::sentinel should provide operator-
Status
new
Section
[range.take.sentinel]
Submitter
Hewill Kang

Created on 2022-07-15.00:00:00 last changed 4 weeks ago

Messages

Date: 2022-07-16.16:16:39

Proposed resolution:

This wording is relative to N4910.

  1. Modify [range.take.sentinel], class template take_view::sentinel synopsis, as indicated:

    namespace std::ranges {
      template<view V>
      template<bool Const>
      class take_view<V>::sentinel {
      private:
        using Base = maybe-const<Const, V>;                                     // exposition only
        template<bool OtherConst>
          using CI = counted_iterator<iterator_t<maybe-const<OtherConst, V>>>;  // exposition only
        sentinel_t<Base> end_ = sentinel_t<Base>();                             // exposition only
      public:
        […]
        friend constexpr bool operator==(const CI<Const>& y, const sentinel& x);
    
        template<bool OtherConst = !Const>
          requires sentinel_for<sentinel_t<Base>, iterator_t<maybe-const<OtherConst, V>>>
        friend constexpr bool operator==(const CI<OtherConst>& y, const sentinel& x);
        
        friend constexpr range_difference_t<Base>
          operator-(const sentinel& x, const CI<Const>& y)
            requires sized_sentinel_for<sentinel_t<Base>, iterator_t<Base>>;
    
        template<bool OtherConst = !Const>
          requires sized_sentinel_for<sentinel_t<Base>, iterator_t<maybe-const<OtherConst, V>>>
        friend constexpr range_difference_t<maybe-const<OtherConst, V>>
          operator-(const sentinel& x, const CI<OtherConst>& y);
    
        friend constexpr range_difference_t<Base>
          operator-(const CI<Const>& x, const sentinel& y)
            requires sized_sentinel_for<sentinel_t<Base>, iterator_t<Base>>;
    
        template<bool OtherConst = !Const>
          requires sized_sentinel_for<sentinel_t<Base>, iterator_t<maybe-const<OtherConst, V>>>
        friend constexpr range_difference_t<maybe-const<OtherConst, V>>
          operator-(const CI<OtherConst>& x, const sentinel& y);
      };
    }
    
    […]
    friend constexpr bool operator==(const CI<Const>& y, const sentinel& x);
    
    template<bool OtherConst = !Const>
      requires sentinel_for<sentinel_t<Base>, iterator_t<maybe-const<OtherConst, V>>>
    friend constexpr bool operator==(const CI<OtherConst>& y, const sentinel& x);
    

    -4- Effects: Equivalent to: return y.count() == 0 || y.base() == x.end_;

    
    friend constexpr range_difference_t<Base> 
      operator-(const sentinel& x, const CI<Const>& y)
        requires sized_sentinel_for<sentinel_t<Base>, iterator_t<Base>>; 
    
    template<bool OtherConst = !Const>
      requires sized_sentinel_for<sentinel_t<Base>, iterator_t<maybe-const<OtherConst, V>>>
    friend constexpr range_difference_t<maybe-const<OtherConst, V>>
      operator-(const sentinel& x, const CI<OtherConst>& y);
    

    -?- Effects: Equivalent to: return ranges::min(y.count(), x.end_ - y.base());

    
    friend constexpr range_difference_t<Base>
      operator-(const CI<Const>& x, const sentinel& y)
        requires sized_sentinel_for<sentinel_t<Base>, iterator_t<Base>>;
    
    template<bool OtherConst = !Const>
      requires sized_sentinel_for<sentinel_t<Base>, iterator_t<maybe-const<OtherConst, V>>>
    friend constexpr range_difference_t<maybe-const<OtherConst, V>>
      operator-(const CI<OtherConst>& x, const sentinel& y);
    
    

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

Date: 2022-07-15.00:00:00

When the underlying range is not a sized_range, the begin and end functions of take_view return counted_iterator and take_view::sentinel respectively. However, the sentinel type of the underlying range may still model sized_sentinel_for for its iterator type, and since take_view::sentinel can only be compared to counted_iterator, this makes take_view no longer able to compute the distance between its iterator and sentinel.

We are needlessly losing functionality here. Since calculating the distance, in this case, is still simple, i.e. we just need to compute the minimum of counted_iterator::count and the difference between the underlying iterator and sentinel, I think providing operator- for take_view::sentinel does bring some value.

History
Date User Action Args
2022-07-16 16:16:39adminsetmessages: + msg12590
2022-07-15 00:00:00admincreate