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