Index: libcxx/include/__iterator/iter_move.h =================================================================== --- libcxx/include/__iterator/iter_move.h +++ libcxx/include/__iterator/iter_move.h @@ -39,6 +39,23 @@ iter_move(std::forward<_Tp>(__t)); }; +template +concept __move_deref = + !__unqualified_iter_move<_Tp> && + requires (_Tp&& __t) { + *__t; + requires is_lvalue_reference_v; + }; + +template +concept __just_deref = + !__unqualified_iter_move<_Tp> && + !__move_deref<_Tp> && + requires (_Tp&& __t) { + *__t; + requires (!is_lvalue_reference_v); + }; + // [iterator.cust.move] struct __fn { @@ -51,17 +68,18 @@ } template - requires (!__unqualified_iter_move<_Ip>) && - requires { *declval<_Ip>(); } - [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr decltype(auto) operator()(_Ip&& __i) const + requires __move_deref<_Ip> + [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr auto operator()(_Ip&& __i) const + noexcept(noexcept(std::move(*std::forward<_Ip>(__i)))) + -> decltype( std::move(*std::forward<_Ip>(__i))) + { return std::move(*std::forward<_Ip>(__i)); } + + template + requires __just_deref<_Ip> + [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr auto operator()(_Ip&& __i) const noexcept(noexcept(*std::forward<_Ip>(__i))) - { - if constexpr (is_lvalue_reference_v())>) { - return std::move(*std::forward<_Ip>(__i)); - } else { - return *std::forward<_Ip>(__i); - } - } + -> decltype( *std::forward<_Ip>(__i)) + { return *std::forward<_Ip>(__i); } }; } // namespace __iter_move Index: libcxx/test/std/iterators/iterator.requirements/iterator.cust/iterator.cust.move/iter_rvalue_reference_t.compile.pass.cpp =================================================================== --- libcxx/test/std/iterators/iterator.requirements/iterator.cust/iterator.cust.move/iter_rvalue_reference_t.compile.pass.cpp +++ libcxx/test/std/iterators/iterator.requirements/iterator.cust/iterator.cust.move/iter_rvalue_reference_t.compile.pass.cpp @@ -14,12 +14,12 @@ #include -#include -#include -#include +static_assert(std::same_as, int&&>); +static_assert(std::same_as, const int&&>); -static_assert(std::same_as::iterator&>, int&&>); -static_assert(std::same_as::const_iterator>, int const&&>); -static_assert(std::same_as::iterator>, int const&&>); - -int main(int, char**) { return 0; } +void test_undefined_internal() { + struct A { + int& operator*() const; + }; + static_assert(std::same_as, int&&>); +}