[libcxx][ranges] Implement indirectly_swappable.
Differential Revision: https://reviews.llvm.org/D105304
NOKEYCHECK=True
GitOrigin-RevId: edc1f0c12c836abaeeab7b0d9f7e8fb73c233ae6
diff --git a/include/__iterator/concepts.h b/include/__iterator/concepts.h
index e3664db..94e5f5d 100644
--- a/include/__iterator/concepts.h
+++ b/include/__iterator/concepts.h
@@ -249,6 +249,9 @@
constructible_from<iter_value_t<_In>, iter_rvalue_reference_t<_In>> &&
assignable_from<iter_value_t<_In>&, iter_rvalue_reference_t<_In>>;
+// Note: indirectly_swappable is located in iter_swap.h to prevent a dependency cycle
+// (both iter_swap and indirectly_swappable require indirectly_readable).
+
// clang-format on
#endif // !defined(_LIBCPP_HAS_NO_RANGES)
diff --git a/include/__iterator/iter_swap.h b/include/__iterator/iter_swap.h
index a529472..1715372 100644
--- a/include/__iterator/iter_swap.h
+++ b/include/__iterator/iter_swap.h
@@ -85,6 +85,16 @@
} // namespace ranges
+template<class _I1, class _I2 = _I1>
+concept indirectly_swappable =
+ indirectly_readable<_I1> && indirectly_readable<_I2> &&
+ requires(const _I1 __i1, const _I2 __i2) {
+ ranges::iter_swap(__i1, __i1);
+ ranges::iter_swap(__i2, __i2);
+ ranges::iter_swap(__i1, __i2);
+ ranges::iter_swap(__i2, __i1);
+ };
+
#endif // !defined(_LIBCPP_HAS_NO_RANGES)
_LIBCPP_END_NAMESPACE_STD
diff --git a/include/iterator b/include/iterator
index b4e15c2..f6b0d2a 100644
--- a/include/iterator
+++ b/include/iterator
@@ -132,6 +132,10 @@
template<class In, class Out>
concept indirectly_movable_storable = see below; // since C++20
+// [alg.req.ind.swap], concept indirectly_swappable
+template<class I1, class I2 = I1>
+ concept indirectly_swappable = see below; // since C++20
+
template<class Category, class T, class Distance = ptrdiff_t,
class Pointer = T*, class Reference = T&>
struct iterator // deprecated in C++17