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