Skip to content

Commit

Permalink
[ranges] Apply resolution of LWG-3502 to elements_view (#1878)
Browse files Browse the repository at this point in the history
Co-authored-by: Casey Carter <[email protected]>
  • Loading branch information
miscco and CaseyCarter authored May 1, 2021
1 parent 02ae70a commit 4946c74
Show file tree
Hide file tree
Showing 2 changed files with 32 additions and 2 deletions.
27 changes: 25 additions & 2 deletions stl/inc/ranges
Original file line number Diff line number Diff line change
Expand Up @@ -3701,10 +3701,14 @@ namespace ranges {
// clang-format on
};

template <class _Tuple, size_t _Index>
concept _Returnable_element = is_reference_v<_Tuple> || move_constructible<tuple_element_t<_Index, _Tuple>>;

// clang-format off
template <input_range _Vw, size_t _Index>
requires view<_Vw> && _Has_tuple_element<range_value_t<_Vw>, _Index>
&& _Has_tuple_element<remove_reference_t<range_reference_t<_Vw>>, _Index>
&& _Returnable_element<range_reference_t<_Vw>, _Index>
class elements_view : public view_interface<elements_view<_Vw, _Index>> {
// clang-format on
private:
Expand Down Expand Up @@ -3767,10 +3771,18 @@ namespace ranges {
}

_NODISCARD constexpr decltype(auto) operator*() const
noexcept(noexcept(_STD get<_Index>(*_Current))) /* strengthened */ {
noexcept(noexcept(_STD get<_Index>(*_Current))) /* strengthened */
requires is_reference_v<range_reference_t<_Base>> {
return _STD get<_Index>(*_Current);
}

_NODISCARD constexpr decltype(auto) operator*() const
noexcept(is_nothrow_move_constructible_v<tuple_element_t<_Index, range_reference_t<_Base>>> //
&& noexcept(_STD get<_Index>(*_Current))) /* strengthened */ {
using _ElemTy = remove_cv_t<tuple_element_t<_Index, range_reference_t<_Base>>>;
return static_cast<_ElemTy>(_STD get<_Index>(*_Current));
}

constexpr _Iterator& operator++() noexcept(noexcept(++_Current)) /* strengthened */ {
++_Current;
return *this;
Expand Down Expand Up @@ -3831,13 +3843,24 @@ namespace ranges {

_NODISCARD constexpr decltype(auto) operator[](const difference_type _Idx) const
noexcept(noexcept(_STD get<_Index>(*(_Current + _Idx)))) /* strengthened */
requires random_access_range<_Base> {
requires random_access_range<_Base>&& is_reference_v<range_reference_t<_Base>> {
#if _ITERATOR_DEBUG_LEVEL != 0
_Verify_offset(_Idx);
#endif // _ITERATOR_DEBUG_LEVEL != 0
return _STD get<_Index>(*(_Current + _Idx));
}

_NODISCARD constexpr decltype(auto) operator[](const difference_type _Idx) const
noexcept(is_nothrow_move_constructible_v<tuple_element_t<_Index, range_reference_t<_Base>>> //
&& noexcept(_STD get<_Index>(*(_Current + _Idx)))) /* strengthened */
requires random_access_range<_Base> {
#if _ITERATOR_DEBUG_LEVEL != 0
_Verify_offset(_Idx);
#endif // _ITERATOR_DEBUG_LEVEL != 0
using _ElemTy = remove_cv_t<tuple_element_t<_Index, range_reference_t<_Base>>>;
return static_cast<_ElemTy>(_STD get<_Index>(*(_Current + _Idx)));
}

_NODISCARD friend constexpr bool operator==(const _Iterator& _Left, const _Iterator& _Right) noexcept(
noexcept(_Left._Current == _Right._Current)) /* strengthened */
requires equality_comparable<iterator_t<_Base>> {
Expand Down
7 changes: 7 additions & 0 deletions tests/std/tests/P0896R4_views_elements/test.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -414,4 +414,11 @@ int main() {
STATIC_ASSERT(test_one(s));
test_one(s);
}

{ // Validate a view borrowed range
constexpr auto v = views::iota(0ull, ranges::size(expected_keys))
| views::transform([](auto i) { return make_pair(expected_keys[i], expected_values[i]); });
STATIC_ASSERT(test_one(v));
test_one(v);
}
}

0 comments on commit 4946c74

Please sign in to comment.