Title
take_view and take_while_view's sentinel<false> not comparable with their const iterator
Status
new
Section
[range.take.sentinel][range.take.while.sentinel]
Submitter
Tim Song

Created on 2020-06-06.00:00:00 last changed 2 months ago

Messages

Date: 2020-08-27.19:44:16

Proposed resolution:

This wording is relative to N4861. It assumes the maybe-const helper introduced by the P/R of LWG 3448.

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

    [Drafting note: Unlike LWG 3448, these operators can't be easily templatized, so the approach taken here is to add an overload for the opposite constness instead. However, because const V may not even be a range (and therefore iterator_t<const V> may not be well-formed), we need to defer instantiating the signature of the new overload until the point of use. ]

    namespace std::ranges {
      template<view V>
      template<bool Const>
      class take_view<V>::sentinel {
      private:
        using Base = conditional_t<Const, const V, V>;  // exposition only
        template<bool OtherConst>
        using CI = counted_iterator<iterator_t<Basemaybe-const<OtherConst, V>>>;  // exposition only
    
        […]
    
        constexpr sentinel_t<Base> base() const;
    
        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 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_;

  2. Modify [range.take.while.sentinel] as indicated:

    namespace std::ranges {
        template<view V, class Pred>
        requires input_range<V> && is_object_v<Pred> &&
                    indirect_unary_predicate<const Pred, iterator_t<V>>
        template<bool Const>
        class take_while_view<V>::sentinel {
          […]
    
          constexpr sentinel_t<Base> base() const { return end_; }
    
          friend constexpr bool operator==(const iterator_t<Base>& x, const sentinel& y);
          
          template<bool OtherConst = !Const>
              requires sentinel_for<sentinel_t<Base>, iterator_t<maybe-const<OtherConst, V>>>
          friend constexpr bool operator==(const iterator_t<maybe-const<OtherConst, V>>& x, const sentinel& y);
          
        };
    }
    
    […]
    friend constexpr bool operator==(const iterator_t<Base>& x, const sentinel& y);
    
    template<bool OtherConst = !Const>
        requires sentinel_for<sentinel_t<Base>, iterator_t<maybe-const<OtherConst, V>>>
    friend constexpr bool operator==(const iterator_t<maybe-const<OtherConst, V>>& x, const sentinel& y);
    
    

    -3- Effects: Equivalent to: return y.end_ == x || !invoke(*y.pred_, *x);

Date: 2020-07-15.00:00:00

[ 2020-07-17; Priority set to 1 in telecon ]

Should be considered together with 3406 and 3448.

Date: 2020-06-15.00:00:00

[ 2020-06-15 Tim corrects a typo in the PR ]

Date: 2020-06-06.00:00:00

During reflector discussion it was noted that the issue observed in LWG 3448 applies to take_view::sentinel and take_while_view::sentinel as well.

History
Date User Action Args
2020-07-17 22:37:26adminsetmessages: + msg11400
2020-06-15 13:30:14adminsetmessages: + msg11336
2020-06-06 13:46:40adminsetmessages: + msg11323
2020-06-06 00:00:00admincreate