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_SWAP_H 11 #define _LIBCPP___ITERATOR_ITER_SWAP_H 12 13 #include <__concepts/class_or_enum.h> 14 #include <__concepts/swappable.h> 15 #include <__config> 16 #include <__iterator/concepts.h> 17 #include <__iterator/iter_move.h> 18 #include <__iterator/iterator_traits.h> 19 #include <__iterator/readable_traits.h> 20 #include <__type_traits/remove_cvref.h> 21 #include <__utility/declval.h> 22 #include <__utility/forward.h> 23 #include <__utility/move.h> 24 25 #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) 26 # pragma GCC system_header 27 #endif 28 29 _LIBCPP_PUSH_MACROS 30 #include <__undef_macros> 31 32 _LIBCPP_BEGIN_NAMESPACE_STD 33 34 #if _LIBCPP_STD_VER >= 20 35 36 // [iter.cust.swap] 37 38 namespace ranges { 39 namespace __iter_swap { 40 template<class _I1, class _I2> 41 void iter_swap(_I1, _I2) = delete; 42 43 template<class _T1, class _T2> 44 concept __unqualified_iter_swap = 45 (__class_or_enum<remove_cvref_t<_T1>> || __class_or_enum<remove_cvref_t<_T2>>) && 46 requires (_T1&& __x, _T2&& __y) { 47 // NOLINTNEXTLINE(libcpp-robust-against-adl) iter_swap ADL calls should only be made through ranges::iter_swap 48 iter_swap(_VSTD::forward<_T1>(__x), _VSTD::forward<_T2>(__y)); 49 }; 50 51 template<class _T1, class _T2> 52 concept __readable_swappable = 53 indirectly_readable<_T1> && indirectly_readable<_T2> && 54 swappable_with<iter_reference_t<_T1>, iter_reference_t<_T2>>; 55 56 57 struct __fn { 58 // NOLINTBEGIN(libcpp-robust-against-adl) iter_swap ADL calls should only be made through ranges::iter_swap 59 template <class _T1, class _T2> 60 requires __unqualified_iter_swap<_T1, _T2> 61 _LIBCPP_HIDE_FROM_ABI 62 constexpr void operator()(_T1&& __x, _T2&& __y) const 63 noexcept(noexcept(iter_swap(_VSTD::forward<_T1>(__x), _VSTD::forward<_T2>(__y)))) 64 { 65 (void)iter_swap(_VSTD::forward<_T1>(__x), _VSTD::forward<_T2>(__y)); 66 } 67 // NOLINTEND(libcpp-robust-against-adl) 68 69 template <class _T1, class _T2> 70 requires (!__unqualified_iter_swap<_T1, _T2>) && 71 __readable_swappable<_T1, _T2> 72 _LIBCPP_HIDE_FROM_ABI 73 constexpr void operator()(_T1&& __x, _T2&& __y) const 74 noexcept(noexcept(ranges::swap(*_VSTD::forward<_T1>(__x), *_VSTD::forward<_T2>(__y)))) 75 { 76 ranges::swap(*_VSTD::forward<_T1>(__x), *_VSTD::forward<_T2>(__y)); 77 } 78 79 template <class _T1, class _T2> 80 requires (!__unqualified_iter_swap<_T1, _T2> && 81 !__readable_swappable<_T1, _T2>) && 82 indirectly_movable_storable<_T1, _T2> && 83 indirectly_movable_storable<_T2, _T1> 84 _LIBCPP_HIDE_FROM_ABI 85 constexpr void operator()(_T1&& __x, _T2&& __y) const 86 noexcept(noexcept(iter_value_t<_T2>(ranges::iter_move(__y))) && 87 noexcept(*__y = ranges::iter_move(__x)) && 88 noexcept(*_VSTD::forward<_T1>(__x) = std::declval<iter_value_t<_T2>>())) 89 { 90 iter_value_t<_T2> __old(ranges::iter_move(__y)); 91 *__y = ranges::iter_move(__x); 92 *_VSTD::forward<_T1>(__x) = _VSTD::move(__old); 93 } 94 }; 95 } // namespace __iter_swap 96 97 inline namespace __cpo { 98 inline constexpr auto iter_swap = __iter_swap::__fn{}; 99 } // namespace __cpo 100 } // namespace ranges 101 102 template<class _I1, class _I2 = _I1> 103 concept indirectly_swappable = 104 indirectly_readable<_I1> && indirectly_readable<_I2> && 105 requires(const _I1 __i1, const _I2 __i2) { 106 ranges::iter_swap(__i1, __i1); 107 ranges::iter_swap(__i2, __i2); 108 ranges::iter_swap(__i1, __i2); 109 ranges::iter_swap(__i2, __i1); 110 }; 111 112 #endif // _LIBCPP_STD_VER >= 20 113 114 _LIBCPP_END_NAMESPACE_STD 115 116 _LIBCPP_POP_MACROS 117 118 #endif // _LIBCPP___ITERATOR_ITER_SWAP_H 119