diff --git a/stl/inc/ranges b/stl/inc/ranges index 98b9df3b14..eb1b986d1a 100644 --- a/stl/inc/ranges +++ b/stl/inc/ranges @@ -3701,10 +3701,14 @@ namespace ranges { // clang-format on }; + template + concept _Returnable_element = is_reference_v<_Tuple> || move_constructible>; + // clang-format off template requires view<_Vw> && _Has_tuple_element, _Index> && _Has_tuple_element>, _Index> + && _Returnable_element, _Index> class elements_view : public view_interface> { // clang-format on private: @@ -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> { return _STD get<_Index>(*_Current); } + _NODISCARD constexpr decltype(auto) operator*() const + noexcept(is_nothrow_move_constructible_v>> // + && noexcept(_STD get<_Index>(*_Current))) /* strengthened */ { + using _ElemTy = remove_cv_t>>; + return static_cast<_ElemTy>(_STD get<_Index>(*_Current)); + } + constexpr _Iterator& operator++() noexcept(noexcept(++_Current)) /* strengthened */ { ++_Current; return *this; @@ -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> { #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>> // + && 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>>; + 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> { diff --git a/tests/std/tests/P0896R4_views_elements/test.cpp b/tests/std/tests/P0896R4_views_elements/test.cpp index 82c58fae69..910ded5e09 100644 --- a/tests/std/tests/P0896R4_views_elements/test.cpp +++ b/tests/std/tests/P0896R4_views_elements/test.cpp @@ -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); + } }