**Section:** 26.7.32.3 [range.cartesian.iterator] **Status:** C++23
**Submitter:** Hewill Kang **Opened:** 2022-08-27 **Last modified:** 2023-11-22 15:47:43 UTC

**Priority: **Not Prioritized

**View all other** issues in [range.cartesian.iterator].

**View all issues with** C++23 status.

**Discussion:**

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

First, ` distance-from` is not

Second, the non-common version of `operator-` passes ` iterator` by value,
which unnecessarily prohibits subtracting

The proposed resolution is to add `const` qualification to ` distance-from`
and make the non-common version of

*[2022-09-08]*

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

*[2022-09-23; Reflector poll]*

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

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

**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) —

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

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

be the sum of*scaled-sum*for every integer*scaled-distance*(*N*)`0 ≤`.*N*≤ sizeof...(Vs)

-8-

*Preconditions*:can be represented by*scaled-sum*`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

be an object of a type that is a specialization of*end-tuple*`tuple`, such that:(32.1) —

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

`std::get<`has the same value as*N*>(*end-tuple*)`ranges::begin(std::get<`for every integer*N*>(i.*parent_*->*bases_*))`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);`