1 // -*- C++ -*- 2 //===----------------------------------------------------------------------===// 3 // 4 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 5 // See https://llvm.org/LICENSE.txt for license information. 6 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 7 // 8 //===----------------------------------------------------------------------===// 9 10 #ifndef _LIBCPP___ITERATOR_ITER_MOVE_H 11 #define _LIBCPP___ITERATOR_ITER_MOVE_H 12 13 #include <__config> 14 #include <__iterator/iterator_traits.h> 15 #include <concepts> // __class_or_enum 16 #include <type_traits> 17 #include <utility> 18 19 #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) 20 #pragma GCC system_header 21 #endif 22 23 _LIBCPP_PUSH_MACROS 24 #include <__undef_macros> 25 26 _LIBCPP_BEGIN_NAMESPACE_STD 27 28 #if !defined(_LIBCPP_HAS_NO_RANGES) 29 30 namespace ranges::__iter_move { 31 void iter_move(); 32 33 template<class _Ip> requires(_Ip && __i)34concept __unqualified_iter_move = requires(_Ip&& __i) { 35 iter_move(_VSTD::forward<_Ip>(__i)); 36 }; 37 38 // [iterator.cust.move]/1 39 // The name ranges::iter_move denotes a customization point object. 40 // The expression ranges::iter_move(E) for a subexpression E is 41 // expression-equivalent to: 42 struct __fn { 43 // [iterator.cust.move]/1.1 44 // iter_move(E), if E has class or enumeration type and iter_move(E) is a 45 // well-formed expression when treated as an unevaluated operand, [...] 46 template<class _Ip> 47 requires __class_or_enum<remove_cvref_t<_Ip>> && __unqualified_iter_move<_Ip> decltype__fn48 [[nodiscard]] constexpr decltype(auto) operator()(_Ip&& __i) const 49 noexcept(noexcept(iter_move(_VSTD::forward<_Ip>(__i)))) 50 { 51 return iter_move(_VSTD::forward<_Ip>(__i)); 52 } 53 54 // [iterator.cust.move]/1.2 55 // Otherwise, if the expression *E is well-formed: 56 // 1.2.1 if *E is an lvalue, std::move(*E); 57 // 1.2.2 otherwise, *E. 58 template<class _Ip> 59 requires (!(__class_or_enum<remove_cvref_t<_Ip>> && __unqualified_iter_move<_Ip>)) && requires__fn60 requires(_Ip&& __i) { *_VSTD::forward<_Ip>(__i); } decltype__fn61 [[nodiscard]] constexpr decltype(auto) operator()(_Ip&& __i) const 62 noexcept(noexcept(*_VSTD::forward<_Ip>(__i))) 63 { 64 if constexpr (is_lvalue_reference_v<decltype(*_VSTD::forward<_Ip>(__i))>) { 65 return _VSTD::move(*_VSTD::forward<_Ip>(__i)); 66 } else { 67 return *_VSTD::forward<_Ip>(__i); 68 } 69 } 70 71 // [iterator.cust.move]/1.3 72 // Otherwise, ranges::iter_move(E) is ill-formed. 73 }; 74 } // namespace ranges::__iter_move 75 76 namespace ranges::inline __cpo { 77 inline constexpr auto iter_move = __iter_move::__fn{}; 78 } 79 80 template<__dereferenceable _Tp> requires(_Tp & __t)81requires requires(_Tp& __t) { { ranges::iter_move(__t) } -> __referenceable; } 82 using iter_rvalue_reference_t = decltype(ranges::iter_move(declval<_Tp&>())); 83 84 #endif // !_LIBCPP_HAS_NO_RANGES 85 86 _LIBCPP_END_NAMESPACE_STD 87 88 _LIBCPP_POP_MACROS 89 90 #endif // _LIBCPP___ITERATOR_ITER_MOVE_H 91