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 #ifndef _LIBCPP___ITERATOR_ITER_SWAP_H 10 #define _LIBCPP___ITERATOR_ITER_SWAP_H 11 12 #include <__config> 13 #include <__iterator/concepts.h> 14 #include <__iterator/iter_move.h> 15 #include <__iterator/iterator_traits.h> 16 #include <__iterator/readable_traits.h> 17 #include <__ranges/access.h> 18 #include <concepts> 19 #include <type_traits> 20 21 #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) 22 #pragma GCC system_header 23 #endif 24 25 _LIBCPP_PUSH_MACROS 26 #include <__undef_macros> 27 28 _LIBCPP_BEGIN_NAMESPACE_STD 29 30 #if !defined(_LIBCPP_HAS_NO_RANGES) 31 32 namespace ranges { 33 namespace __iter_swap { 34 template<class _I1, class _I2> 35 void iter_swap(_I1, _I2) = delete; 36 37 template<class _T1, class _T2> 38 concept __unqualified_iter_swap = requires(_T1&& __x, _T2&& __y) { 39 iter_swap(_VSTD::forward<_T1>(__x), _VSTD::forward<_T2>(__y)); 40 }; 41 42 template<class _T1, class _T2> 43 concept __readable_swappable = 44 indirectly_readable<_T1> && indirectly_readable<_T2> && 45 swappable_with<iter_reference_t<_T1>, iter_reference_t<_T2>>; 46 47 struct __fn { 48 template <class _T1, class _T2> 49 requires __unqualified_iter_swap<_T1, _T2> 50 _LIBCPP_HIDE_FROM_ABI 51 constexpr void operator()(_T1&& __x, _T2&& __y) const 52 noexcept(noexcept(iter_swap(_VSTD::forward<_T1>(__x), _VSTD::forward<_T2>(__y)))) 53 { 54 (void)iter_swap(_VSTD::forward<_T1>(__x), _VSTD::forward<_T2>(__y)); 55 } 56 57 template <class _T1, class _T2> 58 requires (!__unqualified_iter_swap<_T1, _T2>) && 59 __readable_swappable<_T1, _T2> 60 _LIBCPP_HIDE_FROM_ABI 61 constexpr void operator()(_T1&& __x, _T2&& __y) const 62 noexcept(noexcept(ranges::swap(*_VSTD::forward<_T1>(__x), *_VSTD::forward<_T2>(__y)))) 63 { 64 ranges::swap(*_VSTD::forward<_T1>(__x), *_VSTD::forward<_T2>(__y)); 65 } 66 67 template <class _T1, class _T2> 68 requires (!__unqualified_iter_swap<_T1, _T2> && 69 !__readable_swappable<_T1, _T2>) && 70 indirectly_movable_storable<_T1, _T2> && 71 indirectly_movable_storable<_T2, _T1> 72 _LIBCPP_HIDE_FROM_ABI 73 constexpr void operator()(_T1&& __x, _T2&& __y) const 74 noexcept(noexcept(iter_value_t<_T2>(ranges::iter_move(__y))) && 75 noexcept(*__y = ranges::iter_move(__x)) && 76 noexcept(*_VSTD::forward<_T1>(__x) = declval<iter_value_t<_T2>>())) 77 { 78 iter_value_t<_T2> __old(ranges::iter_move(__y)); 79 *__y = ranges::iter_move(__x); 80 *_VSTD::forward<_T1>(__x) = _VSTD::move(__old); 81 } 82 }; 83 } // end namespace __iter_swap 84 85 inline namespace __cpo { 86 inline constexpr auto iter_swap = __iter_swap::__fn{}; 87 } // namespace __cpo 88 89 } // namespace ranges 90 91 template<class _I1, class _I2 = _I1> 92 concept indirectly_swappable = 93 indirectly_readable<_I1> && indirectly_readable<_I2> && 94 requires(const _I1 __i1, const _I2 __i2) { 95 ranges::iter_swap(__i1, __i1); 96 ranges::iter_swap(__i2, __i2); 97 ranges::iter_swap(__i1, __i2); 98 ranges::iter_swap(__i2, __i1); 99 }; 100 101 #endif // !defined(_LIBCPP_HAS_NO_RANGES) 102 103 _LIBCPP_END_NAMESPACE_STD 104 105 _LIBCPP_POP_MACROS 106 107 #endif // _LIBCPP___ITERATOR_ITER_SWAP_H 108