xref: /freebsd/contrib/llvm-project/libcxx/include/__iterator/iter_move.h (revision 0fca6ea1d4eea4c934cfff25ac9ee8ad6fe95583)
1fe6060f1SDimitry Andric // -*- C++ -*-
2fe6060f1SDimitry Andric //===----------------------------------------------------------------------===//
3fe6060f1SDimitry Andric //
4fe6060f1SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
5fe6060f1SDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
6fe6060f1SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
7fe6060f1SDimitry Andric //
8fe6060f1SDimitry Andric //===----------------------------------------------------------------------===//
9fe6060f1SDimitry Andric 
10fe6060f1SDimitry Andric #ifndef _LIBCPP___ITERATOR_ITER_MOVE_H
11fe6060f1SDimitry Andric #define _LIBCPP___ITERATOR_ITER_MOVE_H
12fe6060f1SDimitry Andric 
1381ad6265SDimitry Andric #include <__concepts/class_or_enum.h>
14fe6060f1SDimitry Andric #include <__config>
15fe6060f1SDimitry Andric #include <__iterator/iterator_traits.h>
16bdd1243dSDimitry Andric #include <__type_traits/is_reference.h>
17bdd1243dSDimitry Andric #include <__type_traits/remove_cvref.h>
18bdd1243dSDimitry Andric #include <__utility/declval.h>
19fe6060f1SDimitry Andric #include <__utility/forward.h>
2081ad6265SDimitry Andric #include <__utility/move.h>
21fe6060f1SDimitry Andric 
22fe6060f1SDimitry Andric #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
23fe6060f1SDimitry Andric #  pragma GCC system_header
24fe6060f1SDimitry Andric #endif
25fe6060f1SDimitry Andric 
2606c3fb27SDimitry Andric _LIBCPP_PUSH_MACROS
2706c3fb27SDimitry Andric #include <__undef_macros>
2806c3fb27SDimitry Andric 
29fe6060f1SDimitry Andric _LIBCPP_BEGIN_NAMESPACE_STD
30fe6060f1SDimitry Andric 
3106c3fb27SDimitry Andric #if _LIBCPP_STD_VER >= 20
32fe6060f1SDimitry Andric 
331fd87a68SDimitry Andric // [iterator.cust.move]
341fd87a68SDimitry Andric 
351fd87a68SDimitry Andric namespace ranges {
361fd87a68SDimitry Andric namespace __iter_move {
371fd87a68SDimitry Andric 
38*0fca6ea1SDimitry Andric void iter_move() = delete;
39fe6060f1SDimitry Andric 
401fd87a68SDimitry Andric template <class _Tp>
requires(_Tp && __t)41cb14a3feSDimitry Andric concept __unqualified_iter_move = __class_or_enum<remove_cvref_t<_Tp>> && requires(_Tp&& __t) {
42bdd1243dSDimitry Andric   // NOLINTNEXTLINE(libcpp-robust-against-adl) iter_swap ADL calls should only be made through ranges::iter_swap
4381ad6265SDimitry Andric   iter_move(std::forward<_Tp>(__t));
44fe6060f1SDimitry Andric };
45fe6060f1SDimitry Andric 
4681ad6265SDimitry Andric template <class _Tp>
47cb14a3feSDimitry Andric concept __move_deref = !__unqualified_iter_move<_Tp> && requires(_Tp&& __t) {
4881ad6265SDimitry Andric   *__t;
4981ad6265SDimitry Andric   requires is_lvalue_reference_v<decltype(*__t)>;
5081ad6265SDimitry Andric };
5181ad6265SDimitry Andric 
5281ad6265SDimitry Andric template <class _Tp>
53cb14a3feSDimitry Andric concept __just_deref = !__unqualified_iter_move<_Tp> && !__move_deref<_Tp> && requires(_Tp&& __t) {
5481ad6265SDimitry Andric   *__t;
5581ad6265SDimitry Andric   requires(!is_lvalue_reference_v<decltype(*__t)>);
5681ad6265SDimitry Andric };
5781ad6265SDimitry Andric 
5881ad6265SDimitry Andric // [iterator.cust.move]
5981ad6265SDimitry Andric 
60fe6060f1SDimitry Andric struct __fn {
61bdd1243dSDimitry Andric   // NOLINTBEGIN(libcpp-robust-against-adl) iter_move ADL calls should only be made through ranges::iter_move
62fe6060f1SDimitry Andric   template <class _Ip>
6381ad6265SDimitry Andric     requires __unqualified_iter_move<_Ip>
decltype__fn64fe6060f1SDimitry Andric   [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr decltype(auto) operator()(_Ip&& __i) const
65cb14a3feSDimitry Andric       noexcept(noexcept(iter_move(std::forward<_Ip>(__i)))) {
6681ad6265SDimitry Andric     return iter_move(std::forward<_Ip>(__i));
67fe6060f1SDimitry Andric   }
68bdd1243dSDimitry Andric   // NOLINTEND(libcpp-robust-against-adl)
69fe6060f1SDimitry Andric 
70fe6060f1SDimitry Andric   template <class _Ip>
7181ad6265SDimitry Andric     requires __move_deref<_Ip>
7281ad6265SDimitry Andric   [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr auto operator()(_Ip&& __i) const
73cb14a3feSDimitry Andric       noexcept(noexcept(std::move(*std::forward<_Ip>(__i)))) -> decltype(std::move(*std::forward<_Ip>(__i))) {
74cb14a3feSDimitry Andric     return std::move(*std::forward<_Ip>(__i));
75cb14a3feSDimitry Andric   }
76fe6060f1SDimitry Andric 
7781ad6265SDimitry Andric   template <class _Ip>
7881ad6265SDimitry Andric     requires __just_deref<_Ip>
7981ad6265SDimitry Andric   [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr auto operator()(_Ip&& __i) const
80cb14a3feSDimitry Andric       noexcept(noexcept(*std::forward<_Ip>(__i))) -> decltype(*std::forward<_Ip>(__i)) {
81cb14a3feSDimitry Andric     return *std::forward<_Ip>(__i);
82cb14a3feSDimitry Andric   }
83fe6060f1SDimitry Andric };
841fd87a68SDimitry Andric } // namespace __iter_move
85fe6060f1SDimitry Andric 
861fd87a68SDimitry Andric inline namespace __cpo {
87fe6060f1SDimitry Andric inline constexpr auto iter_move = __iter_move::__fn{};
881fd87a68SDimitry Andric } // namespace __cpo
891fd87a68SDimitry Andric } // namespace ranges
90fe6060f1SDimitry Andric 
91fe6060f1SDimitry Andric template <__dereferenceable _Tp>
requires(_Tp & __t)92cb14a3feSDimitry Andric   requires requires(_Tp& __t) {
93cb14a3feSDimitry Andric     { ranges::iter_move(__t) } -> __can_reference;
94cb14a3feSDimitry Andric   }
95bdd1243dSDimitry Andric using iter_rvalue_reference_t = decltype(ranges::iter_move(std::declval<_Tp&>()));
96fe6060f1SDimitry Andric 
9706c3fb27SDimitry Andric #endif // _LIBCPP_STD_VER >= 20
98fe6060f1SDimitry Andric 
99fe6060f1SDimitry Andric _LIBCPP_END_NAMESPACE_STD
100fe6060f1SDimitry Andric 
10106c3fb27SDimitry Andric _LIBCPP_POP_MACROS
10206c3fb27SDimitry Andric 
103fe6060f1SDimitry Andric #endif // _LIBCPP___ITERATOR_ITER_MOVE_H
104