iter_swap.h 3.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118
  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>>) &&
  37. requires (_T1&& __x, _T2&& __y) {
  38. // NOLINTNEXTLINE(libcpp-robust-against-adl) iter_swap ADL calls should only be made through ranges::iter_swap
  39. iter_swap(_VSTD::forward<_T1>(__x), _VSTD::forward<_T2>(__y));
  40. };
  41. template<class _T1, class _T2>
  42. concept __readable_swappable =
  43. indirectly_readable<_T1> && indirectly_readable<_T2> &&
  44. swappable_with<iter_reference_t<_T1>, iter_reference_t<_T2>>;
  45. struct __fn {
  46. // NOLINTBEGIN(libcpp-robust-against-adl) iter_swap ADL calls should only be made through ranges::iter_swap
  47. template <class _T1, class _T2>
  48. requires __unqualified_iter_swap<_T1, _T2>
  49. _LIBCPP_HIDE_FROM_ABI
  50. constexpr void operator()(_T1&& __x, _T2&& __y) const
  51. noexcept(noexcept(iter_swap(_VSTD::forward<_T1>(__x), _VSTD::forward<_T2>(__y))))
  52. {
  53. (void)iter_swap(_VSTD::forward<_T1>(__x), _VSTD::forward<_T2>(__y));
  54. }
  55. // NOLINTEND(libcpp-robust-against-adl)
  56. template <class _T1, class _T2>
  57. requires (!__unqualified_iter_swap<_T1, _T2>) &&
  58. __readable_swappable<_T1, _T2>
  59. _LIBCPP_HIDE_FROM_ABI
  60. constexpr void operator()(_T1&& __x, _T2&& __y) const
  61. noexcept(noexcept(ranges::swap(*_VSTD::forward<_T1>(__x), *_VSTD::forward<_T2>(__y))))
  62. {
  63. ranges::swap(*_VSTD::forward<_T1>(__x), *_VSTD::forward<_T2>(__y));
  64. }
  65. template <class _T1, class _T2>
  66. requires (!__unqualified_iter_swap<_T1, _T2> &&
  67. !__readable_swappable<_T1, _T2>) &&
  68. indirectly_movable_storable<_T1, _T2> &&
  69. indirectly_movable_storable<_T2, _T1>
  70. _LIBCPP_HIDE_FROM_ABI
  71. constexpr void operator()(_T1&& __x, _T2&& __y) const
  72. noexcept(noexcept(iter_value_t<_T2>(ranges::iter_move(__y))) &&
  73. noexcept(*__y = ranges::iter_move(__x)) &&
  74. noexcept(*_VSTD::forward<_T1>(__x) = std::declval<iter_value_t<_T2>>()))
  75. {
  76. iter_value_t<_T2> __old(ranges::iter_move(__y));
  77. *__y = ranges::iter_move(__x);
  78. *_VSTD::forward<_T1>(__x) = _VSTD::move(__old);
  79. }
  80. };
  81. } // namespace __iter_swap
  82. inline namespace __cpo {
  83. inline constexpr auto iter_swap = __iter_swap::__fn{};
  84. } // namespace __cpo
  85. } // namespace ranges
  86. template<class _I1, class _I2 = _I1>
  87. concept indirectly_swappable =
  88. indirectly_readable<_I1> && indirectly_readable<_I2> &&
  89. requires(const _I1 __i1, const _I2 __i2) {
  90. ranges::iter_swap(__i1, __i1);
  91. ranges::iter_swap(__i2, __i2);
  92. ranges::iter_swap(__i1, __i2);
  93. ranges::iter_swap(__i2, __i1);
  94. };
  95. #endif // _LIBCPP_STD_VER >= 20
  96. _LIBCPP_END_NAMESPACE_STD
  97. _LIBCPP_POP_MACROS
  98. #endif // _LIBCPP___ITERATOR_ITER_SWAP_H