2 //===----------------------------------------------------------------------===//
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
8 //===----------------------------------------------------------------------===//
10 #ifndef _LIBCPP___ITERATOR_ITER_SWAP_H
11 #define _LIBCPP___ITERATOR_ITER_SWAP_H
13 #include <__concepts/class_or_enum.h>
14 #include <__concepts/swappable.h>
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>
25 #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
26 # pragma GCC system_header
30 #include <__undef_macros>
32 _LIBCPP_BEGIN_NAMESPACE_STD
34 #if _LIBCPP_STD_VER >= 20
39 namespace __iter_swap
{
40 template<class _I1
, class _I2
>
41 void iter_swap(_I1
, _I2
) = delete;
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
));
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
>>;
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
>
62 constexpr void operator()(_T1
&& __x
, _T2
&& __y
) const
63 noexcept(noexcept(iter_swap(_VSTD::forward
<_T1
>(__x
), _VSTD::forward
<_T2
>(__y
))))
65 (void)iter_swap(_VSTD::forward
<_T1
>(__x
), _VSTD::forward
<_T2
>(__y
));
67 // NOLINTEND(libcpp-robust-against-adl)
69 template <class _T1
, class _T2
>
70 requires (!__unqualified_iter_swap
<_T1
, _T2
>) &&
71 __readable_swappable
<_T1
, _T2
>
73 constexpr void operator()(_T1
&& __x
, _T2
&& __y
) const
74 noexcept(noexcept(ranges::swap(*_VSTD::forward
<_T1
>(__x
), *_VSTD::forward
<_T2
>(__y
))))
76 ranges::swap(*_VSTD::forward
<_T1
>(__x
), *_VSTD::forward
<_T2
>(__y
));
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
>
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
>>()))
90 iter_value_t
<_T2
> __old(ranges::iter_move(__y
));
91 *__y
= ranges::iter_move(__x
);
92 *_VSTD::forward
<_T1
>(__x
) = _VSTD::move(__old
);
95 } // namespace __iter_swap
97 inline namespace __cpo
{
98 inline constexpr auto iter_swap
= __iter_swap::__fn
{};
100 } // namespace ranges
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
);
112 #endif // _LIBCPP_STD_VER >= 20
114 _LIBCPP_END_NAMESPACE_STD
118 #endif // _LIBCPP___ITERATOR_ITER_SWAP_H