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 <__utility/forward.h> 16 #include <concepts> // __class_or_enum 17 #include <type_traits> 18 #include <utility> 19 20 #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) 21 #pragma GCC system_header 22 #endif 23 24 _LIBCPP_BEGIN_NAMESPACE_STD 25 26 #if !defined(_LIBCPP_HAS_NO_RANGES) 27 28 namespace ranges::__iter_move { 29 void iter_move(); 30 31 template<class _Ip> 32 concept __unqualified_iter_move = requires(_Ip&& __i) { 33 iter_move(_VSTD::forward<_Ip>(__i)); 34 }; 35 36 // [iterator.cust.move]/1 37 // The name ranges::iter_move denotes a customization point object. 38 // The expression ranges::iter_move(E) for a subexpression E is 39 // expression-equivalent to: 40 struct __fn { 41 // [iterator.cust.move]/1.1 42 // iter_move(E), if E has class or enumeration type and iter_move(E) is a 43 // well-formed expression when treated as an unevaluated operand, [...] 44 template<class _Ip> 45 requires __class_or_enum<remove_cvref_t<_Ip>> && __unqualified_iter_move<_Ip> 46 [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr decltype(auto) operator()(_Ip&& __i) const 47 noexcept(noexcept(iter_move(_VSTD::forward<_Ip>(__i)))) 48 { 49 return iter_move(_VSTD::forward<_Ip>(__i)); 50 } 51 52 // [iterator.cust.move]/1.2 53 // Otherwise, if the expression *E is well-formed: 54 // 1.2.1 if *E is an lvalue, std::move(*E); 55 // 1.2.2 otherwise, *E. 56 template<class _Ip> 57 requires (!(__class_or_enum<remove_cvref_t<_Ip>> && __unqualified_iter_move<_Ip>)) && 58 requires(_Ip&& __i) { *_VSTD::forward<_Ip>(__i); } 59 [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr decltype(auto) operator()(_Ip&& __i) const 60 noexcept(noexcept(*_VSTD::forward<_Ip>(__i))) 61 { 62 if constexpr (is_lvalue_reference_v<decltype(*_VSTD::forward<_Ip>(__i))>) { 63 return _VSTD::move(*_VSTD::forward<_Ip>(__i)); 64 } else { 65 return *_VSTD::forward<_Ip>(__i); 66 } 67 } 68 69 // [iterator.cust.move]/1.3 70 // Otherwise, ranges::iter_move(E) is ill-formed. 71 }; 72 } // namespace ranges::__iter_move 73 74 namespace ranges::inline __cpo { 75 inline constexpr auto iter_move = __iter_move::__fn{}; 76 } 77 78 template<__dereferenceable _Tp> 79 requires requires(_Tp& __t) { { ranges::iter_move(__t) } -> __referenceable; } 80 using iter_rvalue_reference_t = decltype(ranges::iter_move(declval<_Tp&>())); 81 82 #endif // !_LIBCPP_HAS_NO_RANGES 83 84 _LIBCPP_END_NAMESPACE_STD 85 86 #endif // _LIBCPP___ITERATOR_ITER_MOVE_H 87