*This page is a snapshot from the LWG issues list, see the Library Active Issues List for more information and the meaning of C++23 status.*

`cartesian_product_view::`*iterator*::*prev*

is not quite right**Section:** 26.7.33.3 [range.cartesian.iterator] **Status:** C++23
**Submitter:** Hewill Kang **Opened:** 2022-11-08 **Last modified:** 2023-11-22

**Priority: **Not Prioritized

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

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

**Discussion:**

Currently, `cartesian_product_view::`

has the following *iterator*::*prev**Effects*:

auto& it = std::get<N>(current_); if (it == ranges::begin(std::get<N>(parent_->bases_))) { it =cartesian-common-arg-end(std::get<N>(parent_->bases_)); if constexpr (N > 0) {prev<N - 1>(); } } --it;

which decrements the underlying iterator one by one using recursion.
However, when `N == 0`

, it still detects if the first iterator has reached the beginning and assigns it to
the end, which is not only unnecessary, but also causes

to be applied to
the first range, making it ill-formed in some cases, for example:
*cartesian-common-arg-end*

```
#include <ranges>
int main() {
auto r = std::views::cartesian_product(std::views::iota(0));
r.begin() += 3; // hard error
}
```

This is because, for the first range, `cartesian_product_view::`

only requires
it to model *iterator*::operator+=`random_access_range`

.
However, when `x`

is negative, this function will call

and indirectly calls
*prev*

, since the latter constrains its argument to satisfy
*cartesian-common-arg-end*

, that is, *cartesian-product-common-arg*```
common_range<R> || (sized_range<R> &&
random_access_range<R>)
```

, which is not the case for the unbounded `iota_view`

, resulting in a
hard error in

's function body.
*prev*

The proposed resolution changes the position of the `if constexpr`

so that we just decrement the first
iterator and nothing else.

*[Kona 2022-11-08; Move to Ready]*

*[2023-02-13 Approved at February 2023 meeting in Issaquah. Status changed: Voting → WP.]*

**Proposed resolution:**

This wording is relative to N4917.

Modify [ranges.cartesian.iterator] as indicated:

template<size_t N = sizeof...(Vs)> constexpr void

*prev*();-6-

*Effects*: Equivalent to:auto& it = std::get<N>(

*current_*); if constexpr (N > 0) { if (it == ranges::begin(std::get<N>(*parent_*->*bases_*))) { it =*cartesian-common-arg-end*(std::get<N>(*parent_*->*bases_*));~~if constexpr (N > 0) {~~*prev*<N - 1>();~~}~~} } --it;