iter_swap.h 3.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108
  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. #include <__concepts/class_or_enum.h>
  12. #include <__concepts/swappable.h>
  13. #include <__config>
  14. #include <__iterator/concepts.h>
  15. #include <__iterator/iter_move.h>
  16. #include <__iterator/iterator_traits.h>
  17. #include <__iterator/readable_traits.h>
  18. #include <__type_traits/remove_cvref.h>
  19. #include <__utility/declval.h>
  20. #include <__utility/forward.h>
  21. #include <__utility/move.h>
  22. #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
  23. # pragma GCC system_header
  24. #endif
  25. _LIBCPP_PUSH_MACROS
  26. #include <__undef_macros>
  27. _LIBCPP_BEGIN_NAMESPACE_STD
  28. #if _LIBCPP_STD_VER >= 20
  29. // [iter.cust.swap]
  30. namespace ranges {
  31. namespace __iter_swap {
  32. template <class _I1, class _I2>
  33. void iter_swap(_I1, _I2) = delete;
  34. template <class _T1, class _T2>
  35. concept __unqualified_iter_swap =
  36. (__class_or_enum<remove_cvref_t<_T1>> || __class_or_enum<remove_cvref_t<_T2>>)&&requires(_T1&& __x, _T2&& __y) {
  37. // NOLINTNEXTLINE(libcpp-robust-against-adl) iter_swap ADL calls should only be made through ranges::iter_swap
  38. iter_swap(std::forward<_T1>(__x), std::forward<_T2>(__y));
  39. };
  40. template <class _T1, class _T2>
  41. concept __readable_swappable =
  42. indirectly_readable<_T1> && indirectly_readable<_T2> &&
  43. swappable_with<iter_reference_t<_T1>, iter_reference_t<_T2>>;
  44. struct __fn {
  45. // NOLINTBEGIN(libcpp-robust-against-adl) iter_swap ADL calls should only be made through ranges::iter_swap
  46. template <class _T1, class _T2>
  47. requires __unqualified_iter_swap<_T1, _T2>
  48. _LIBCPP_HIDE_FROM_ABI constexpr void operator()(_T1&& __x, _T2&& __y) const
  49. noexcept(noexcept(iter_swap(std::forward<_T1>(__x), std::forward<_T2>(__y)))) {
  50. (void)iter_swap(std::forward<_T1>(__x), std::forward<_T2>(__y));
  51. }
  52. // NOLINTEND(libcpp-robust-against-adl)
  53. template <class _T1, class _T2>
  54. requires(!__unqualified_iter_swap<_T1, _T2>) && __readable_swappable<_T1, _T2>
  55. _LIBCPP_HIDE_FROM_ABI constexpr void operator()(_T1&& __x, _T2&& __y) const
  56. noexcept(noexcept(ranges::swap(*std::forward<_T1>(__x), *std::forward<_T2>(__y)))) {
  57. ranges::swap(*std::forward<_T1>(__x), *std::forward<_T2>(__y));
  58. }
  59. template <class _T1, class _T2>
  60. requires(!__unqualified_iter_swap<_T1, _T2> && //
  61. !__readable_swappable<_T1, _T2>) && //
  62. indirectly_movable_storable<_T1, _T2> && //
  63. indirectly_movable_storable<_T2, _T1>
  64. _LIBCPP_HIDE_FROM_ABI constexpr void operator()(_T1&& __x, _T2&& __y) const
  65. noexcept(noexcept(iter_value_t<_T2>(ranges::iter_move(__y))) && //
  66. noexcept(*__y = ranges::iter_move(__x)) && //
  67. noexcept(*std::forward<_T1>(__x) = std::declval<iter_value_t<_T2>>())) {
  68. iter_value_t<_T2> __old(ranges::iter_move(__y));
  69. *__y = ranges::iter_move(__x);
  70. *std::forward<_T1>(__x) = std::move(__old);
  71. }
  72. };
  73. } // namespace __iter_swap
  74. inline namespace __cpo {
  75. inline constexpr auto iter_swap = __iter_swap::__fn{};
  76. } // namespace __cpo
  77. } // namespace ranges
  78. template <class _I1, class _I2 = _I1>
  79. concept indirectly_swappable =
  80. indirectly_readable<_I1> && indirectly_readable<_I2> && requires(const _I1 __i1, const _I2 __i2) {
  81. ranges::iter_swap(__i1, __i1);
  82. ranges::iter_swap(__i2, __i2);
  83. ranges::iter_swap(__i1, __i2);
  84. ranges::iter_swap(__i2, __i1);
  85. };
  86. #endif // _LIBCPP_STD_VER >= 20
  87. _LIBCPP_END_NAMESPACE_STD
  88. _LIBCPP_POP_MACROS
  89. #endif // _LIBCPP___ITERATOR_ITER_SWAP_H