This page is a snapshot from the LWG issues list, see the Library Active Issues List for more information and the meaning of Resolved status.
join_view::iterator::operator--
may be ill-formedSection: 25.7.14.3 [range.join.iterator] Status: Resolved Submitter: Hewill Kang Opened: 2022-09-30 Last modified: 2023-03-23
Priority: 3
View all other issues in [range.join.iterator].
View all issues with Resolved status.
Discussion:
Currently, join_view::iterator::operator--
has the following Effects:
if (outer_ == ranges::end(parent_->base_)) inner_ = ranges::end(*--outer_); while (inner_ == ranges::begin(*outer_)) inner_ = ranges::end(*--outer_); --inner_; return *this;
which uses ranges::end(*--outer_)
to get the sentinel of the inner range.
However, *--outer_
may return an rvalue reference to a non-borrowed range,
in which case calling ranges::end
will be ill-formed,
for example:
#include <ranges>
#include <vector>
int main() {
std::vector<std::vector<int>> v;
auto r = v | std::views::transform([](auto& x) -> auto&& { return std::move(x); })
| std::views::join;
auto e = --r.end(); // hard error
}
The proposed resolution uses a temporary reference to bind *--outer_
, so that
ranges::end
is always invoked on an lvalue range, which is consistent with the behavior of
join_with_view::iterator::operator--
.
[2022-10-12; Reflector poll]
Set priority to 3 after reflector poll.
"Could introduce an as_lvalue
lambda (like
auto as_lvalue = []<class T>(T&& x) -> T& { return (T&)x; };
) and use it throughout."
Previous resolution [SUPERSEDED]:
This wording is relative to N4917.
Modify 25.7.14.3 [range.join.iterator] as indicated:
constexpr iterator& operator--() requires ref-is-glvalue && bidirectional_range<Base> && bidirectional_range<range_reference_t<Base>> && common_range<range_reference_t<Base>>;-13- Effects: Equivalent to:
if (outer_ == ranges::end(parent_->base_)) { auto&& inner = *--outer_; inner_ = ranges::end(inner*--outer_); } while (trueinner_ == ranges::begin(*outer_)) { if (auto&& tmp = *outer_; inner_ == ranges::begin(tmp)) { auto&& inner = *--outer_; inner_ = ranges::end(inner*--outer_); } else { break; } } --inner_; return *this;
[2023-03-22 Resolved by the adoption of P2770R0 in Issaquah. Status changed: New → Resolved.]
Proposed resolution: