[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