Created on 2022-08-27.00:00:00 last changed 13 months ago
Proposed resolution:
This wording is relative to n4917.
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:
(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);
(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
(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:
(32.1) — std::get<0>(end-tuple) has the same value as ranges::end(std::get<0>(i.parent_->bases_));
(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);
[ 2022-11-12 Approved at November 2022 meeting in Kona. Status changed: Voting → WP. ]
[ 2022-09-23; Reflector poll ]
Set status to Tentatively Ready after six votes in favour during reflector poll.
[ 2022-09-08 ]
As suggested by Tim Song, the originally submitted proposed wording has been refined to use const Tuple& instead of Tuple&.
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:43 | admin | set | status: wp -> c++23 |
2022-11-17 00:42:33 | admin | set | messages: + msg13068 |
2022-11-17 00:42:33 | admin | set | status: voting -> wp |
2022-11-08 03:46:49 | admin | set | status: ready -> voting |
2022-09-23 15:43:32 | admin | set | messages: + msg12790 |
2022-09-23 15:43:32 | admin | set | status: new -> ready |
2022-09-08 07:05:16 | admin | set | messages: + msg12751 |
2022-09-03 14:43:41 | admin | set | messages: + msg12730 |
2022-08-27 00:00:00 | admin | create |