diff --git a/stl/inc/xutility b/stl/inc/xutility index 7a66539e1c0..42a4a6b9173 100644 --- a/stl/inc/xutility +++ b/stl/inc/xutility @@ -1758,6 +1758,9 @@ _NODISCARD constexpr const _Elem* data(initializer_list<_Elem> _Ilist) noexcept _EXPORT_STD template using iter_const_reference_t = common_reference_t&&, iter_reference_t<_Ty>>; +template +using _Iter_const_rvalue_reference_t = common_reference_t&&, iter_rvalue_reference_t<_Iter>>; + template concept _Constant_iterator = input_iterator<_Ty> && same_as, iter_reference_t<_Ty>>; @@ -1810,7 +1813,8 @@ class basic_const_iterator : public _Basic_const_iterator_category<_Iter> { private: /* [[no_unique_address]] */ _Iter _Current{}; - using _Reference = iter_const_reference_t<_Iter>; + using _Reference = iter_const_reference_t<_Iter>; + using _Rvalue_reference = _Iter_const_rvalue_reference_t<_Iter>; _NODISCARD static _CONSTEVAL auto _Get_iter_concept() noexcept { if constexpr (contiguous_iterator<_Iter>) { @@ -2063,6 +2067,11 @@ public: noexcept(_Se - _It._Current)) /* strengthened */ { // per LWG-3769 return _Se - _It._Current; } + + _NODISCARD_FRIEND constexpr _Rvalue_reference iter_move(const basic_const_iterator& _It) noexcept( + noexcept(static_cast<_Rvalue_reference>(_RANGES iter_move(_It._Current)))) { + return static_cast<_Rvalue_reference>(_RANGES iter_move(_It._Current)); + } }; template _Ty2> diff --git a/tests/std/tests/P2278R4_basic_const_iterator/env.lst b/tests/std/tests/P2278R4_basic_const_iterator/env.lst index 18e2d7c71ec..8ac7033b206 100644 --- a/tests/std/tests/P2278R4_basic_const_iterator/env.lst +++ b/tests/std/tests/P2278R4_basic_const_iterator/env.lst @@ -1,4 +1,4 @@ # Copyright (c) Microsoft Corporation. # SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -RUNALL_INCLUDE ..\concepts_latest_matrix.lst +RUNALL_INCLUDE ..\strict_concepts_latest_matrix.lst diff --git a/tests/std/tests/P2278R4_basic_const_iterator/test.cpp b/tests/std/tests/P2278R4_basic_const_iterator/test.cpp index 660c201c581..2c8ab8bbf64 100644 --- a/tests/std/tests/P2278R4_basic_const_iterator/test.cpp +++ b/tests/std/tests/P2278R4_basic_const_iterator/test.cpp @@ -4,6 +4,7 @@ #include #include #include +#include #include #include @@ -239,6 +240,13 @@ constexpr void test_one(It iter) { static_assert(noexcept(citer == sent) == noexcept(iter == sent)); // strengthened } + { // Validate basic_const_iterator::iter_move() + using Expected = common_reference_t&&, iter_rvalue_reference_t>; + [[maybe_unused]] same_as decltype(auto) val = ranges::iter_move(citer); + static_assert( + noexcept(ranges::iter_move(citer)) == noexcept(static_cast(ranges::iter_move(citer.base())))); + } + { // Validate basic_const_iterator::base() const& [[maybe_unused]] same_as decltype(auto) base = citer.base(); static_assert(noexcept(citer.base())); @@ -252,6 +260,10 @@ constexpr void test_one(It iter) { static constexpr int some_ints[] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10}; +// Check LWG-3872 +using Zipped = decltype(views::zip(some_ints) | views::as_const | views::as_rvalue); +static_assert(same_as, tuple>); + struct instantiator { template static constexpr void call() {