1fe6060f1SDimitry Andric // -*- C++ -*- 2fe6060f1SDimitry Andric //===----------------------------------------------------------------------===// 3fe6060f1SDimitry Andric // 4fe6060f1SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 5fe6060f1SDimitry Andric // See https://llvm.org/LICENSE.txt for license information. 6fe6060f1SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 7fe6060f1SDimitry Andric // 8fe6060f1SDimitry Andric //===----------------------------------------------------------------------===// 9bdd1243dSDimitry Andric 10fe6060f1SDimitry Andric #ifndef _LIBCPP___ITERATOR_ITER_SWAP_H 11fe6060f1SDimitry Andric #define _LIBCPP___ITERATOR_ITER_SWAP_H 12fe6060f1SDimitry Andric 13bdd1243dSDimitry Andric #include <__concepts/class_or_enum.h> 14bdd1243dSDimitry Andric #include <__concepts/swappable.h> 15fe6060f1SDimitry Andric #include <__config> 16fe6060f1SDimitry Andric #include <__iterator/concepts.h> 17fe6060f1SDimitry Andric #include <__iterator/iter_move.h> 18fe6060f1SDimitry Andric #include <__iterator/iterator_traits.h> 19fe6060f1SDimitry Andric #include <__iterator/readable_traits.h> 20bdd1243dSDimitry Andric #include <__type_traits/remove_cvref.h> 21bdd1243dSDimitry Andric #include <__utility/declval.h> 22349cc55cSDimitry Andric #include <__utility/forward.h> 23349cc55cSDimitry Andric #include <__utility/move.h> 24fe6060f1SDimitry Andric 25fe6060f1SDimitry Andric #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) 26fe6060f1SDimitry Andric # pragma GCC system_header 27fe6060f1SDimitry Andric #endif 28fe6060f1SDimitry Andric 2906c3fb27SDimitry Andric _LIBCPP_PUSH_MACROS 3006c3fb27SDimitry Andric #include <__undef_macros> 3106c3fb27SDimitry Andric 32fe6060f1SDimitry Andric _LIBCPP_BEGIN_NAMESPACE_STD 33fe6060f1SDimitry Andric 3406c3fb27SDimitry Andric #if _LIBCPP_STD_VER >= 20 351fd87a68SDimitry Andric 361fd87a68SDimitry Andric // [iter.cust.swap] 37fe6060f1SDimitry Andric 38fe6060f1SDimitry Andric namespace ranges { 39fe6060f1SDimitry Andric namespace __iter_swap { 40fe6060f1SDimitry Andric template <class _I1, class _I2> 41fe6060f1SDimitry Andric void iter_swap(_I1, _I2) = delete; 42fe6060f1SDimitry Andric 43fe6060f1SDimitry Andric template <class _T1, class _T2> 441fd87a68SDimitry Andric concept __unqualified_iter_swap = requires(_T1 && __x,_T2 && __y)45*cb14a3feSDimitry Andric (__class_or_enum<remove_cvref_t<_T1>> || __class_or_enum<remove_cvref_t<_T2>>) && requires(_T1&& __x, _T2&& __y) { 46bdd1243dSDimitry Andric // NOLINTNEXTLINE(libcpp-robust-against-adl) iter_swap ADL calls should only be made through ranges::iter_swap 475f757f3fSDimitry Andric iter_swap(std::forward<_T1>(__x), std::forward<_T2>(__y)); 48fe6060f1SDimitry Andric }; 49fe6060f1SDimitry Andric 50fe6060f1SDimitry Andric template <class _T1, class _T2> 51fe6060f1SDimitry Andric concept __readable_swappable = 52fe6060f1SDimitry Andric indirectly_readable<_T1> && indirectly_readable<_T2> && 53fe6060f1SDimitry Andric swappable_with<iter_reference_t<_T1>, iter_reference_t<_T2>>; 54fe6060f1SDimitry Andric 55fe6060f1SDimitry Andric struct __fn { 56bdd1243dSDimitry Andric // NOLINTBEGIN(libcpp-robust-against-adl) iter_swap ADL calls should only be made through ranges::iter_swap 57fe6060f1SDimitry Andric template <class _T1, class _T2> 58fe6060f1SDimitry Andric requires __unqualified_iter_swap<_T1, _T2> operator__fn59*cb14a3feSDimitry Andric _LIBCPP_HIDE_FROM_ABI constexpr void operator()(_T1&& __x, _T2&& __y) const 60*cb14a3feSDimitry Andric noexcept(noexcept(iter_swap(std::forward<_T1>(__x), std::forward<_T2>(__y)))) { 615f757f3fSDimitry Andric (void)iter_swap(std::forward<_T1>(__x), std::forward<_T2>(__y)); 62fe6060f1SDimitry Andric } 63bdd1243dSDimitry Andric // NOLINTEND(libcpp-robust-against-adl) 64fe6060f1SDimitry Andric 65fe6060f1SDimitry Andric template <class _T1, class _T2> 66*cb14a3feSDimitry Andric requires(!__unqualified_iter_swap<_T1, _T2>) && __readable_swappable<_T1, _T2> operator__fn67*cb14a3feSDimitry Andric _LIBCPP_HIDE_FROM_ABI constexpr void operator()(_T1&& __x, _T2&& __y) const 68*cb14a3feSDimitry Andric noexcept(noexcept(ranges::swap(*std::forward<_T1>(__x), *std::forward<_T2>(__y)))) { 695f757f3fSDimitry Andric ranges::swap(*std::forward<_T1>(__x), *std::forward<_T2>(__y)); 70fe6060f1SDimitry Andric } 71fe6060f1SDimitry Andric 72fe6060f1SDimitry Andric template <class _T1, class _T2> 735f757f3fSDimitry Andric requires(!__unqualified_iter_swap<_T1, _T2> && // 745f757f3fSDimitry Andric !__readable_swappable<_T1, _T2>) && // 755f757f3fSDimitry Andric indirectly_movable_storable<_T1, _T2> && // 76fe6060f1SDimitry Andric indirectly_movable_storable<_T2, _T1> operator__fn77*cb14a3feSDimitry Andric _LIBCPP_HIDE_FROM_ABI constexpr void operator()(_T1&& __x, _T2&& __y) const 785f757f3fSDimitry Andric noexcept(noexcept(iter_value_t<_T2>(ranges::iter_move(__y))) && // 795f757f3fSDimitry Andric noexcept(*__y = ranges::iter_move(__x)) && // 80*cb14a3feSDimitry Andric noexcept(*std::forward<_T1>(__x) = std::declval<iter_value_t<_T2>>())) { 81fe6060f1SDimitry Andric iter_value_t<_T2> __old(ranges::iter_move(__y)); 82fe6060f1SDimitry Andric *__y = ranges::iter_move(__x); 835f757f3fSDimitry Andric *std::forward<_T1>(__x) = std::move(__old); 84fe6060f1SDimitry Andric } 85fe6060f1SDimitry Andric }; 861fd87a68SDimitry Andric } // namespace __iter_swap 87fe6060f1SDimitry Andric 88fe6060f1SDimitry Andric inline namespace __cpo { 89fe6060f1SDimitry Andric inline constexpr auto iter_swap = __iter_swap::__fn{}; 90fe6060f1SDimitry Andric } // namespace __cpo 91fe6060f1SDimitry Andric } // namespace ranges 92fe6060f1SDimitry Andric 93fe6060f1SDimitry Andric template <class _I1, class _I2 = _I1> 94fe6060f1SDimitry Andric concept indirectly_swappable = requires(const _I1 __i1,const _I2 __i2)95*cb14a3feSDimitry Andric indirectly_readable<_I1> && indirectly_readable<_I2> && requires(const _I1 __i1, const _I2 __i2) { 96fe6060f1SDimitry Andric ranges::iter_swap(__i1, __i1); 97fe6060f1SDimitry Andric ranges::iter_swap(__i2, __i2); 98fe6060f1SDimitry Andric ranges::iter_swap(__i1, __i2); 99fe6060f1SDimitry Andric ranges::iter_swap(__i2, __i1); 100fe6060f1SDimitry Andric }; 101fe6060f1SDimitry Andric 10206c3fb27SDimitry Andric #endif // _LIBCPP_STD_VER >= 20 103fe6060f1SDimitry Andric 104fe6060f1SDimitry Andric _LIBCPP_END_NAMESPACE_STD 105fe6060f1SDimitry Andric 10606c3fb27SDimitry Andric _LIBCPP_POP_MACROS 10706c3fb27SDimitry Andric 108fe6060f1SDimitry Andric #endif // _LIBCPP___ITERATOR_ITER_SWAP_H 109