This page is a snapshot from the LWG issues list, see the Library Active Issues List for more information and the meaning of C++20 status.
Section: 26.7.14.3 [range.join.iterator] Status: C++20 Submitter: United States Opened: 2019-11-04 Last modified: 2021-02-25
Priority: 0
View all other issues in [range.join.iterator].
View all issues with C++20 status.
Discussion:
Addresses US 294
join_view::iterator::operator-- is improperly constrained. In the Effects: clause in paragraph 14, we see the statement:
inner_ = ranges::end(*--outer_);
However, this only well-formed when end returns an iterator, not a sentinel. This requirement is not reflected in the constraints of the function(s).
Eric Niebler: From the WD, join_view::iterator::operator-- is specified as:constexpr iterator& operator--() requires ref_is_glvalue && bidirectional_range<Base> && bidirectional_range<range_reference_t<Base>>;-14- Effects: Equivalent to:if (outer_ == ranges::end(parent_->base_)) inner_ = ranges::end(*--outer_); while (inner_ == ranges::begin(*outer_)) inner_ = ranges::end(*--outer_); --inner_; return *this;
The trouble is from the lines that do:
inner_ = ranges::end(*--outer_);
Clearly this will only compile when *--outer returns a common_range, but nowhere is that requirement stated.
[2019-11 Status to Ready during Tuesday morning issue processing in Belfast.]
Proposed resolution:
This wording is relative to N4835.
Modify 26.7.14.3 [range.join.iterator], class template join_view::iterator synopsis, as indicated:
constexpr iterator& operator--() requires ref_is_glvalue && bidirectional_range<Base> && bidirectional_range<range_reference_t<Base>> && common_range<range_reference_t<Base>>; constexpr iterator operator--(int) requires ref_is_glvalue && bidirectional_range<Base> && bidirectional_range<range_reference_t<Base>> && common_range<range_reference_t<Base>>;
Modify 26.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>>;-14- Effects: Equivalent to:
if (outer_ == ranges::end(parent_->base_)) inner_ = ranges::end(*--outer_); while (inner_ == ranges::begin(*outer_)) inner_ = ranges::end(*--outer_); --inner_; return *this;constexpr iterator operator--(int) requires ref_is_glvalue && bidirectional_range<Base> && bidirectional_range<range_reference_t<Base>> && common_range<range_reference_t<Base>>;-15- Effects: Equivalent to:
auto tmp = *this; --*this; return tmp;