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