iter_swap.h 3.5 KB

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