Title
cartesian_product_view::iterator::operator- should pass by reference
Status
c++23
Section
[range.cartesian.iterator]
Submitter
Hewill Kang

Created on 2022-08-27.00:00:00 last changed 12 months ago

Messages

Date: 2022-11-17.00:42:33

Proposed resolution:

This wording is relative to n4917.

  1. Modify [ranges.cartesian.iterator] as indicated:

    namespace std::ranges {
      template<input_range First, forward_range... Vs>
        requires (view<First> && ... && view<Vs>)
      template<bool Const>
      class cartesian_product_view<First, Vs...>::iterator {
      public:
        […]
    
        friend constexpr difference_type operator-(const iterator& i, default_sentinel_t)
          requires cartesian-is-sized-sentinel<Const, sentinel_t, First, Vs...>;
        friend constexpr difference_type operator-(default_sentinel_t, const iterator& i)
          requires cartesian-is-sized-sentinel<Const, sentinel_t, First, Vs...>;
    
        […]
      private:
        […]
        
        template<class Tuple>
          constexpr difference_type distance-from(const Tuple& t) const;            // exposition only
          
        […]
      };
    }
    

    […]

    template<class Tuple>
      constexpr difference_type distance-from(const Tuple& t) const;
    

    -7- Let:

    1. (7.1) — scaled-size(N) be the product of static_cast<difference_type>(ranges::size(std::get<N>(parent_->bases_))) and scaled-size(N + 1) if N < sizeof...(Vs), otherwise static_cast<difference_type>(1);

    2. (7.2) — scaled-distance(N) be the product of static_cast<difference_type>(std::get<N>(current_) - std::get<N>(t)) and scaled-size(N + 1); and

    3. (7.3) — scaled-sum be the sum of scaled-distance(N) for every integer 0 ≤ N ≤ sizeof...(Vs).

    -8- Preconditions: scaled-sum can be represented by difference_type.

    -9- Returns: scaled-sum.

    […]

    friend constexpr difference_type operator-(const iterator& i, default_sentinel_t)
      requires cartesian-is-sized-sentinel<Const, sentinel_t, First, Vs...>;
    

    -32- Let end-tuple be an object of a type that is a specialization of tuple, such that:

    1. (32.1) — std::get<0>(end-tuple) has the same value as ranges::end(std::get<0>(i.parent_->bases_));

    2. (32.2) — std::get<N>(end-tuple) has the same value as ranges::begin(std::get<N>(i.parent_->bases_)) for every integer 1 ≤ N ≤ sizeof...(Vs).

    -33- Effects: Equivalent to: return i.distance-from(end-tuple);

    friend constexpr difference_type operator-(default_sentinel_t, const iterator& i)
      requires cartesian-is-sized-sentinel<Const, sentinel_t, First, Vs...>;
    

    -34- Effects: Equivalent to: return -(i - s);

Date: 2022-11-12.00:00:00

[ 2022-11-12 Approved at November 2022 meeting in Kona. Status changed: Voting → WP. ]

Date: 2022-09-15.00:00:00

[ 2022-09-23; Reflector poll ]

Set status to Tentatively Ready after six votes in favour during reflector poll.

Date: 2022-09-08.00:00:00

[ 2022-09-08 ]

As suggested by Tim Song, the originally submitted proposed wording has been refined to use const Tuple& instead of Tuple&.

Date: 2022-08-27.00:00:00

There are two problems with cartesian_product_view::iterator::operator-.

First, distance-from is not const-qualified, which would cause the common version of operator- to produce a hard error inside the function body since it invokes distance-from on a const iterator object.

Second, the non-common version of operator- passes iterator by value, which unnecessarily prohibits subtracting default_sentinel from an lvalue iterator whose first underlying iterator is non-copyable. Even if we std::move it into operator-, the other overload will still be ill-formed since it returns -(i - s) which will calls i's deleted copy constructor.

The proposed resolution is to add const qualification to distance-from and make the non-common version of iterator::operator- pass by const reference. Although the Tuple parameter of distance-from is guaranteed to be copyable, I think it would be more appropriate to pass it by reference.

History
Date User Action Args
2023-11-22 15:47:43adminsetstatus: wp -> c++23
2022-11-17 00:42:33adminsetmessages: + msg13068
2022-11-17 00:42:33adminsetstatus: voting -> wp
2022-11-08 03:46:49adminsetstatus: ready -> voting
2022-09-23 15:43:32adminsetmessages: + msg12790
2022-09-23 15:43:32adminsetstatus: new -> ready
2022-09-08 07:05:16adminsetmessages: + msg12751
2022-09-03 14:43:41adminsetmessages: + msg12730
2022-08-27 00:00:00admincreate