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