[libcxx-commits] [libcxx] 075f237 - [libcxx][ranges] Add `indirectly_movable` and `indirectly_movable_storable`.

via libcxx-commits libcxx-commits at lists.llvm.org
Mon Jun 21 12:40:27 PDT 2021


Author: zoecarver
Date: 2021-06-21T12:39:25-07:00
New Revision: 075f2370c7fa5495649d09be8b1a9802b17a7f2b

URL: https://github.com/llvm/llvm-project/commit/075f2370c7fa5495649d09be8b1a9802b17a7f2b
DIFF: https://github.com/llvm/llvm-project/commit/075f2370c7fa5495649d09be8b1a9802b17a7f2b.diff

LOG: [libcxx][ranges] Add `indirectly_movable` and `indirectly_movable_storable`.

Differential Revision: https://reviews.llvm.org/D102639

Added: 
    libcxx/test/std/iterators/iterator.requirements/alg.req.ind.move/indirectly_movable.compile.pass.cpp
    libcxx/test/std/iterators/iterator.requirements/alg.req.ind.move/indirectly_movable.subsumption.compile.pass.cpp
    libcxx/test/std/iterators/iterator.requirements/alg.req.ind.move/indirectly_movable_storable.compile.pass.cpp
    libcxx/test/std/iterators/iterator.requirements/alg.req.ind.move/indirectly_movable_storable.subsumption.compile.pass.cpp
    libcxx/test/std/iterators/iterator.requirements/alg.req.ind.move/{ind.move.subsumption.compile.pass.cpp}

Modified: 
    libcxx/include/__iterator/concepts.h
    libcxx/include/iterator
    libcxx/test/std/containers/associative/map/iterator_concept_conformance.compile.pass.cpp
    libcxx/test/std/containers/associative/multimap/iterator_concept_conformance.compile.pass.cpp
    libcxx/test/std/containers/associative/multiset/iterator_concept_conformance.compile.pass.cpp
    libcxx/test/std/containers/associative/set/iterator_concept_conformance.compile.pass.cpp
    libcxx/test/std/containers/sequences/array/iterator_concept_conformance.compile.pass.cpp
    libcxx/test/std/containers/sequences/deque/iterator_concept_conformance.compile.pass.cpp
    libcxx/test/std/containers/sequences/forwardlist/forwardlist.iter/iterator_concept_conformance.compile.pass.cpp
    libcxx/test/std/containers/sequences/list/iterator_concept_conformance.compile.pass.cpp
    libcxx/test/std/containers/sequences/vector.bool/iterator_concept_conformance.compile.pass.cpp
    libcxx/test/std/containers/sequences/vector/iterator_concept_conformance.compile.pass.cpp
    libcxx/test/std/containers/unord/unord.map/iterator_concept_conformance.compile.pass.cpp
    libcxx/test/std/containers/unord/unord.multimap/iterator_concept_conformance.compile.pass.cpp
    libcxx/test/std/containers/unord/unord.multiset/iterator_concept_conformance.compile.pass.cpp
    libcxx/test/std/containers/unord/unord.set/iterator_concept_conformance.compile.pass.cpp
    libcxx/test/std/containers/views/span.iterators/iterator_concept_conformance.compile.pass.cpp
    libcxx/test/std/input.output/filesystems/class.directory_iterator/iterator_concept_conformance.compile.pass.cpp
    libcxx/test/std/iterators/predef.iterators/insert.iterators/back.insert.iterator/iterator_concept_conformance.compile.pass.cpp
    libcxx/test/std/iterators/predef.iterators/insert.iterators/front.insert.iterator/iterator_concept_conformance.compile.pass.cpp
    libcxx/test/std/iterators/predef.iterators/insert.iterators/insert.iterator/iterator_concept_conformance.compile.pass.cpp
    libcxx/test/std/iterators/predef.iterators/move.iterators/move.iterator/iterator_concept_conformance.compile.pass.cpp
    libcxx/test/std/iterators/predef.iterators/reverse.iterators/iterator_concept_conformance.compile.pass.cpp
    libcxx/test/std/iterators/stream.iterators/istream.iterator/iterator_concept_conformance.compile.pass.cpp
    libcxx/test/std/iterators/stream.iterators/istreambuf.iterator/iterator_concept_conformance.compile.pass.cpp
    libcxx/test/std/iterators/stream.iterators/ostream.iterator/iterator_concept_conformance.compile.pass.cpp
    libcxx/test/std/iterators/stream.iterators/ostreambuf.iterator/iterator_concept_conformance.compile.pass.cpp
    libcxx/test/std/re/re.iter/re.regiter/iterator_concept_conformance.compile.pass.cpp
    libcxx/test/std/re/re.iter/re.tokiter/iterator_concept_conformance.compile.pass.cpp
    libcxx/test/std/strings/basic.string/string.iterators/iterator_concept_conformance.compile.pass.cpp
    libcxx/test/std/strings/string.view/string.view.iterators/iterator_concept_conformance.compile.pass.cpp
    libcxx/test/std/utilities/memory/unique.ptr/iterator_concept_conformance.compile.pass.cpp
    libcxx/test/std/utilities/memory/util.smartptr/util.smartptr.shared/iterator_concept_conformance.compile.pass.cpp
    libcxx/test/std/utilities/optional/iterator_concept_conformance.compile.pass.cpp

Removed: 
    


################################################################################
diff  --git a/libcxx/include/__iterator/concepts.h b/libcxx/include/__iterator/concepts.h
index a65413180027c..95f68914836b0 100644
--- a/libcxx/include/__iterator/concepts.h
+++ b/libcxx/include/__iterator/concepts.h
@@ -167,7 +167,6 @@ concept contiguous_iterator =
     { _VSTD::to_address(__i) } -> same_as<add_pointer_t<iter_reference_t<_Ip>>>;
   };
 
-
 template<class _Ip>
 concept __has_arrow = input_iterator<_Ip> && (is_pointer_v<_Ip> || requires(_Ip __i) { __i.operator->(); });
 
@@ -236,6 +235,19 @@ template<class _Fp, class... _Its>
   requires (indirectly_readable<_Its> && ...) && invocable<_Fp, iter_reference_t<_Its>...>
 using indirect_result_t = invoke_result_t<_Fp, iter_reference_t<_Its>...>;
 
+template<class _In, class _Out>
+concept indirectly_movable =
+  indirectly_readable<_In> &&
+  indirectly_writable<_Out, iter_rvalue_reference_t<_In>>;
+
+template<class _In, class _Out>
+concept indirectly_movable_storable =
+  indirectly_movable<_In, _Out> &&
+  indirectly_writable<_Out, iter_value_t<_In>> &&
+  movable<iter_value_t<_In>> &&
+  constructible_from<iter_value_t<_In>, iter_rvalue_reference_t<_In>> &&
+  assignable_from<iter_value_t<_In>&, iter_rvalue_reference_t<_In>>;
+
 // clang-format on
 
 #endif // !defined(_LIBCPP_HAS_NO_RANGES)

diff  --git a/libcxx/include/iterator b/libcxx/include/iterator
index 08faf4d931af8..929cc164384eb 100644
--- a/libcxx/include/iterator
+++ b/libcxx/include/iterator
@@ -125,6 +125,13 @@ template<indirectly_readable I, indirectly_regular_unary_invocable<I> Proj>
 template<weakly_incrementable I, indirectly_regular_unary_invocable<I> Proj>
   struct incrementable_traits<projected<I, Proj>>;         // since C++20
 
+// [alg.req.ind.move], concept indirectly_movable
+template<class In, class Out>
+  concept indirectly_movable = see below;                  // since C++20
+
+template<class In, class Out>
+  concept indirectly_movable_storable = see below;         // since C++20
+
 template<class Category, class T, class Distance = ptr
diff _t,
          class Pointer = T*, class Reference = T&>
 struct iterator                                            // deprecated in C++17

diff  --git a/libcxx/test/std/containers/associative/map/iterator_concept_conformance.compile.pass.cpp b/libcxx/test/std/containers/associative/map/iterator_concept_conformance.compile.pass.cpp
index c74dcfa5a7470..43fa91d8a451a 100644
--- a/libcxx/test/std/containers/associative/map/iterator_concept_conformance.compile.pass.cpp
+++ b/libcxx/test/std/containers/associative/map/iterator_concept_conformance.compile.pass.cpp
@@ -33,6 +33,8 @@ static_assert(!std::sized_sentinel_for<iterator, iterator>);
 static_assert(!std::sized_sentinel_for<iterator, const_iterator>);
 static_assert(!std::sized_sentinel_for<iterator, reverse_iterator>);
 static_assert(!std::sized_sentinel_for<iterator, const_reverse_iterator>);
+static_assert( std::indirectly_movable<iterator, std::pair<int, int>*>);
+static_assert(!std::indirectly_movable_storable<iterator, std::pair<int, int>*>);
 
 static_assert(std::bidirectional_iterator<const_iterator>);
 static_assert(!std::random_access_iterator<const_iterator>);

diff  --git a/libcxx/test/std/containers/associative/multimap/iterator_concept_conformance.compile.pass.cpp b/libcxx/test/std/containers/associative/multimap/iterator_concept_conformance.compile.pass.cpp
index 21a612ac350e2..539d01e002ef0 100644
--- a/libcxx/test/std/containers/associative/multimap/iterator_concept_conformance.compile.pass.cpp
+++ b/libcxx/test/std/containers/associative/multimap/iterator_concept_conformance.compile.pass.cpp
@@ -33,6 +33,8 @@ static_assert(!std::sized_sentinel_for<iterator, iterator>);
 static_assert(!std::sized_sentinel_for<iterator, const_iterator>);
 static_assert(!std::sized_sentinel_for<iterator, reverse_iterator>);
 static_assert(!std::sized_sentinel_for<iterator, const_reverse_iterator>);
+static_assert( std::indirectly_movable<iterator, std::pair<int, int>*>);
+static_assert(!std::indirectly_movable_storable<iterator, std::pair<int, int>*>);
 
 static_assert(std::bidirectional_iterator<const_iterator>);
 static_assert(!std::random_access_iterator<const_iterator>);

diff  --git a/libcxx/test/std/containers/associative/multiset/iterator_concept_conformance.compile.pass.cpp b/libcxx/test/std/containers/associative/multiset/iterator_concept_conformance.compile.pass.cpp
index 6c89f2df7d7f5..0b44c3ed40694 100644
--- a/libcxx/test/std/containers/associative/multiset/iterator_concept_conformance.compile.pass.cpp
+++ b/libcxx/test/std/containers/associative/multiset/iterator_concept_conformance.compile.pass.cpp
@@ -33,6 +33,8 @@ static_assert(!std::sized_sentinel_for<iterator, iterator>);
 static_assert(!std::sized_sentinel_for<iterator, const_iterator>);
 static_assert(!std::sized_sentinel_for<iterator, reverse_iterator>);
 static_assert(!std::sized_sentinel_for<iterator, const_reverse_iterator>);
+static_assert(std::indirectly_movable<iterator, int*>);
+static_assert(std::indirectly_movable_storable<iterator, int*>);
 
 static_assert(std::bidirectional_iterator<const_iterator>);
 static_assert(!std::random_access_iterator<const_iterator>);

diff  --git a/libcxx/test/std/containers/associative/set/iterator_concept_conformance.compile.pass.cpp b/libcxx/test/std/containers/associative/set/iterator_concept_conformance.compile.pass.cpp
index f33771f20926f..76b42fef33943 100644
--- a/libcxx/test/std/containers/associative/set/iterator_concept_conformance.compile.pass.cpp
+++ b/libcxx/test/std/containers/associative/set/iterator_concept_conformance.compile.pass.cpp
@@ -33,6 +33,8 @@ static_assert(!std::sized_sentinel_for<iterator, iterator>);
 static_assert(!std::sized_sentinel_for<iterator, const_iterator>);
 static_assert(!std::sized_sentinel_for<iterator, reverse_iterator>);
 static_assert(!std::sized_sentinel_for<iterator, const_reverse_iterator>);
+static_assert(std::indirectly_movable<iterator, int*>);
+static_assert(std::indirectly_movable_storable<iterator, int*>);
 
 static_assert(std::bidirectional_iterator<const_iterator>);
 static_assert(!std::random_access_iterator<const_iterator>);

diff  --git a/libcxx/test/std/containers/sequences/array/iterator_concept_conformance.compile.pass.cpp b/libcxx/test/std/containers/sequences/array/iterator_concept_conformance.compile.pass.cpp
index 0987835fcda07..29a0f3ade42a8 100644
--- a/libcxx/test/std/containers/sequences/array/iterator_concept_conformance.compile.pass.cpp
+++ b/libcxx/test/std/containers/sequences/array/iterator_concept_conformance.compile.pass.cpp
@@ -31,6 +31,14 @@ static_assert(std::sized_sentinel_for<iterator, iterator>);
 static_assert(std::sized_sentinel_for<iterator, const_iterator>);
 static_assert(!std::sized_sentinel_for<iterator, reverse_iterator>);
 static_assert(!std::sized_sentinel_for<iterator, const_reverse_iterator>);
+static_assert( std::indirectly_movable<iterator, iterator>);
+static_assert( std::indirectly_movable_storable<iterator, iterator>);
+static_assert(!std::indirectly_movable<iterator, const_iterator>);
+static_assert(!std::indirectly_movable_storable<iterator, const_iterator>);
+static_assert( std::indirectly_movable<iterator, reverse_iterator>);
+static_assert( std::indirectly_movable_storable<iterator, reverse_iterator>);
+static_assert(!std::indirectly_movable<iterator, const_reverse_iterator>);
+static_assert(!std::indirectly_movable_storable<iterator, const_reverse_iterator>);
 
 static_assert(std::contiguous_iterator<const_iterator>);
 static_assert(!std::indirectly_writable<const_iterator, int>);
@@ -42,3 +50,11 @@ static_assert(std::sized_sentinel_for<const_iterator, iterator>);
 static_assert(std::sized_sentinel_for<const_iterator, const_iterator>);
 static_assert(!std::sized_sentinel_for<const_iterator, reverse_iterator>);
 static_assert(!std::sized_sentinel_for<const_iterator, const_reverse_iterator>);
+static_assert( std::indirectly_movable<const_iterator, iterator>);
+static_assert( std::indirectly_movable_storable<const_iterator, iterator>);
+static_assert(!std::indirectly_movable<const_iterator, const_iterator>);
+static_assert(!std::indirectly_movable_storable<const_iterator, const_iterator>);
+static_assert( std::indirectly_movable<const_iterator, reverse_iterator>);
+static_assert( std::indirectly_movable_storable<const_iterator, reverse_iterator>);
+static_assert(!std::indirectly_movable<const_iterator, const_reverse_iterator>);
+static_assert(!std::indirectly_movable_storable<const_iterator, const_reverse_iterator>);

diff  --git a/libcxx/test/std/containers/sequences/deque/iterator_concept_conformance.compile.pass.cpp b/libcxx/test/std/containers/sequences/deque/iterator_concept_conformance.compile.pass.cpp
index 248e34b51572e..1b1bf60272f2e 100644
--- a/libcxx/test/std/containers/sequences/deque/iterator_concept_conformance.compile.pass.cpp
+++ b/libcxx/test/std/containers/sequences/deque/iterator_concept_conformance.compile.pass.cpp
@@ -33,6 +33,14 @@ static_assert(std::sized_sentinel_for<iterator, iterator>);
 static_assert(std::sized_sentinel_for<iterator, const_iterator>);
 static_assert(!std::sized_sentinel_for<iterator, reverse_iterator>);
 static_assert(!std::sized_sentinel_for<iterator, const_reverse_iterator>);
+static_assert( std::indirectly_movable<iterator, iterator>);
+static_assert( std::indirectly_movable_storable<iterator, iterator>);
+static_assert(!std::indirectly_movable<iterator, const_iterator>);
+static_assert(!std::indirectly_movable_storable<iterator, const_iterator>);
+static_assert( std::indirectly_movable<iterator, reverse_iterator>);
+static_assert( std::indirectly_movable_storable<iterator, reverse_iterator>);
+static_assert(!std::indirectly_movable<iterator, const_reverse_iterator>);
+static_assert(!std::indirectly_movable_storable<iterator, const_reverse_iterator>);
 
 static_assert(std::random_access_iterator<const_iterator>);
 static_assert(!std::contiguous_iterator<const_iterator>);
@@ -45,3 +53,11 @@ static_assert(std::sized_sentinel_for<const_iterator, iterator>);
 static_assert(std::sized_sentinel_for<const_iterator, const_iterator>);
 static_assert(!std::sized_sentinel_for<const_iterator, reverse_iterator>);
 static_assert(!std::sized_sentinel_for<const_iterator, const_reverse_iterator>);
+static_assert( std::indirectly_movable<const_iterator, iterator>);
+static_assert( std::indirectly_movable_storable<const_iterator, iterator>);
+static_assert(!std::indirectly_movable<const_iterator, const_iterator>);
+static_assert(!std::indirectly_movable_storable<const_iterator, const_iterator>);
+static_assert( std::indirectly_movable<const_iterator, reverse_iterator>);
+static_assert( std::indirectly_movable_storable<const_iterator, reverse_iterator>);
+static_assert(!std::indirectly_movable<const_iterator, const_reverse_iterator>);
+static_assert(!std::indirectly_movable_storable<const_iterator, const_reverse_iterator>);

diff  --git a/libcxx/test/std/containers/sequences/forwardlist/forwardlist.iter/iterator_concept_conformance.compile.pass.cpp b/libcxx/test/std/containers/sequences/forwardlist/forwardlist.iter/iterator_concept_conformance.compile.pass.cpp
index 6a3edcbd98b5d..8caa26e1fde3f 100644
--- a/libcxx/test/std/containers/sequences/forwardlist/forwardlist.iter/iterator_concept_conformance.compile.pass.cpp
+++ b/libcxx/test/std/containers/sequences/forwardlist/forwardlist.iter/iterator_concept_conformance.compile.pass.cpp
@@ -27,6 +27,10 @@ static_assert(std::sentinel_for<iterator, iterator>);
 static_assert(std::sentinel_for<iterator, const_iterator>);
 static_assert(!std::sized_sentinel_for<iterator, iterator>);
 static_assert(!std::sized_sentinel_for<iterator, const_iterator>);
+static_assert( std::indirectly_movable<iterator, iterator>);
+static_assert( std::indirectly_movable_storable<iterator, iterator>);
+static_assert(!std::indirectly_movable<iterator, const_iterator>);
+static_assert(!std::indirectly_movable_storable<iterator, const_iterator>);
 
 static_assert(std::forward_iterator<const_iterator>);
 static_assert(!std::bidirectional_iterator<const_iterator>);
@@ -35,3 +39,7 @@ static_assert(std::sentinel_for<const_iterator, iterator>);
 static_assert(std::sentinel_for<const_iterator, const_iterator>);
 static_assert(!std::sized_sentinel_for<const_iterator, iterator>);
 static_assert(!std::sized_sentinel_for<const_iterator, const_iterator>);
+static_assert( std::indirectly_movable<const_iterator, iterator>);
+static_assert( std::indirectly_movable_storable<const_iterator, iterator>);
+static_assert(!std::indirectly_movable<const_iterator, const_iterator>);
+static_assert(!std::indirectly_movable_storable<const_iterator, const_iterator>);

diff  --git a/libcxx/test/std/containers/sequences/list/iterator_concept_conformance.compile.pass.cpp b/libcxx/test/std/containers/sequences/list/iterator_concept_conformance.compile.pass.cpp
index fe3e1486ecfda..2a4ffe57d9000 100644
--- a/libcxx/test/std/containers/sequences/list/iterator_concept_conformance.compile.pass.cpp
+++ b/libcxx/test/std/containers/sequences/list/iterator_concept_conformance.compile.pass.cpp
@@ -33,6 +33,14 @@ static_assert(!std::sized_sentinel_for<iterator, iterator>);
 static_assert(!std::sized_sentinel_for<iterator, const_iterator>);
 static_assert(!std::sized_sentinel_for<iterator, reverse_iterator>);
 static_assert(!std::sized_sentinel_for<iterator, const_reverse_iterator>);
+static_assert( std::indirectly_movable<iterator, iterator>);
+static_assert( std::indirectly_movable_storable<iterator, iterator>);
+static_assert(!std::indirectly_movable<iterator, const_iterator>);
+static_assert(!std::indirectly_movable_storable<iterator, const_iterator>);
+static_assert( std::indirectly_movable<iterator, reverse_iterator>);
+static_assert( std::indirectly_movable_storable<iterator, reverse_iterator>);
+static_assert(!std::indirectly_movable<iterator, const_reverse_iterator>);
+static_assert(!std::indirectly_movable_storable<iterator, const_reverse_iterator>);
 
 static_assert(std::bidirectional_iterator<const_iterator>);
 static_assert(!std::random_access_iterator<const_iterator>);
@@ -45,3 +53,11 @@ static_assert(!std::sized_sentinel_for<const_iterator, iterator>);
 static_assert(!std::sized_sentinel_for<const_iterator, const_iterator>);
 static_assert(!std::sized_sentinel_for<const_iterator, reverse_iterator>);
 static_assert(!std::sized_sentinel_for<const_iterator, const_reverse_iterator>);
+static_assert( std::indirectly_movable<const_iterator, iterator>);
+static_assert( std::indirectly_movable_storable<const_iterator, iterator>);
+static_assert(!std::indirectly_movable<const_iterator, const_iterator>);
+static_assert(!std::indirectly_movable_storable<const_iterator, const_iterator>);
+static_assert( std::indirectly_movable<const_iterator, reverse_iterator>);
+static_assert( std::indirectly_movable_storable<const_iterator, reverse_iterator>);
+static_assert(!std::indirectly_movable<const_iterator, const_reverse_iterator>);
+static_assert(!std::indirectly_movable_storable<const_iterator, const_reverse_iterator>);

diff  --git a/libcxx/test/std/containers/sequences/vector.bool/iterator_concept_conformance.compile.pass.cpp b/libcxx/test/std/containers/sequences/vector.bool/iterator_concept_conformance.compile.pass.cpp
index 7f5f87b2f8186..037383af0308f 100644
--- a/libcxx/test/std/containers/sequences/vector.bool/iterator_concept_conformance.compile.pass.cpp
+++ b/libcxx/test/std/containers/sequences/vector.bool/iterator_concept_conformance.compile.pass.cpp
@@ -22,30 +22,32 @@ using reverse_iterator = std::vector<bool>::reverse_iterator;
 using const_reverse_iterator = std::vector<bool>::const_reverse_iterator;
 using value_type = bool;
 
-static_assert(std::random_access_iterator<iterator>);
-static_assert(std::random_access_iterator<reverse_iterator>);
+static_assert( std::random_access_iterator<iterator>);
+static_assert( std::random_access_iterator<reverse_iterator>);
 static_assert(!std::contiguous_iterator<iterator>);
 static_assert(!std::contiguous_iterator<reverse_iterator>);
 static_assert(!std::indirectly_writable<iterator, value_type>);
-static_assert(std::sentinel_for<iterator, iterator>);
-static_assert(std::sentinel_for<iterator, const_iterator>);
+static_assert( std::sentinel_for<iterator, iterator>);
+static_assert( std::sentinel_for<iterator, const_iterator>);
 static_assert(!std::sentinel_for<iterator, reverse_iterator>);
 static_assert(!std::sentinel_for<iterator, const_reverse_iterator>);
-static_assert(std::sized_sentinel_for<iterator, iterator>);
-static_assert(std::sized_sentinel_for<iterator, const_iterator>);
+static_assert( std::sized_sentinel_for<iterator, iterator>);
+static_assert( std::sized_sentinel_for<iterator, const_iterator>);
 static_assert(!std::sized_sentinel_for<iterator, reverse_iterator>);
 static_assert(!std::sized_sentinel_for<iterator, const_reverse_iterator>);
+static_assert(std::indirectly_movable<iterator, bool*>);
+static_assert(std::indirectly_movable_storable<iterator, bool*>);
 
-static_assert(std::random_access_iterator<const_iterator>);
-static_assert(std::random_access_iterator<const_reverse_iterator>);
+static_assert( std::random_access_iterator<const_iterator>);
+static_assert( std::random_access_iterator<const_reverse_iterator>);
 static_assert(!std::contiguous_iterator<const_iterator>);
 static_assert(!std::contiguous_iterator<const_reverse_iterator>);
 static_assert(!std::indirectly_writable<const_iterator, value_type>);
-static_assert(std::sentinel_for<const_iterator, iterator>);
-static_assert(std::sentinel_for<const_iterator, const_iterator>);
+static_assert( std::sentinel_for<const_iterator, iterator>);
+static_assert( std::sentinel_for<const_iterator, const_iterator>);
 static_assert(!std::sentinel_for<const_iterator, reverse_iterator>);
 static_assert(!std::sentinel_for<const_iterator, const_reverse_iterator>);
-static_assert(std::sized_sentinel_for<const_iterator, iterator>);
-static_assert(std::sized_sentinel_for<const_iterator, const_iterator>);
+static_assert( std::sized_sentinel_for<const_iterator, iterator>);
+static_assert( std::sized_sentinel_for<const_iterator, const_iterator>);
 static_assert(!std::sized_sentinel_for<const_iterator, reverse_iterator>);
 static_assert(!std::sized_sentinel_for<const_iterator, const_reverse_iterator>);

diff  --git a/libcxx/test/std/containers/sequences/vector/iterator_concept_conformance.compile.pass.cpp b/libcxx/test/std/containers/sequences/vector/iterator_concept_conformance.compile.pass.cpp
index e1160dc5f7df4..3af726723176b 100644
--- a/libcxx/test/std/containers/sequences/vector/iterator_concept_conformance.compile.pass.cpp
+++ b/libcxx/test/std/containers/sequences/vector/iterator_concept_conformance.compile.pass.cpp
@@ -22,28 +22,44 @@ using reverse_iterator = std::vector<int>::reverse_iterator;
 using const_reverse_iterator = std::vector<int>::const_reverse_iterator;
 using value_type = int;
 
-static_assert(std::contiguous_iterator<iterator>);
-static_assert(std::random_access_iterator<reverse_iterator>);
+static_assert( std::contiguous_iterator<iterator>);
+static_assert( std::random_access_iterator<reverse_iterator>);
 static_assert(!std::contiguous_iterator<reverse_iterator>);
-static_assert(std::indirectly_writable<iterator, value_type>);
-static_assert(std::sentinel_for<iterator, iterator>);
-static_assert(std::sentinel_for<iterator, const_iterator>);
+static_assert( std::indirectly_writable<iterator, value_type>);
+static_assert( std::sentinel_for<iterator, iterator>);
+static_assert( std::sentinel_for<iterator, const_iterator>);
 static_assert(!std::sentinel_for<iterator, reverse_iterator>);
 static_assert(!std::sentinel_for<iterator, const_reverse_iterator>);
-static_assert(std::sized_sentinel_for<iterator, iterator>);
-static_assert(std::sized_sentinel_for<iterator, const_iterator>);
+static_assert( std::sized_sentinel_for<iterator, iterator>);
+static_assert( std::sized_sentinel_for<iterator, const_iterator>);
 static_assert(!std::sized_sentinel_for<iterator, reverse_iterator>);
 static_assert(!std::sized_sentinel_for<iterator, const_reverse_iterator>);
+static_assert( std::indirectly_movable<iterator, iterator>);
+static_assert( std::indirectly_movable_storable<iterator, iterator>);
+static_assert(!std::indirectly_movable<iterator, const_iterator>);
+static_assert(!std::indirectly_movable_storable<iterator, const_iterator>);
+static_assert( std::indirectly_movable<iterator, reverse_iterator>);
+static_assert( std::indirectly_movable_storable<iterator, reverse_iterator>);
+static_assert(!std::indirectly_movable<iterator, const_reverse_iterator>);
+static_assert(!std::indirectly_movable_storable<iterator, const_reverse_iterator>);
 
-static_assert(std::contiguous_iterator<const_iterator>);
-static_assert(std::random_access_iterator<const_reverse_iterator>);
+static_assert( std::contiguous_iterator<const_iterator>);
+static_assert( std::random_access_iterator<const_reverse_iterator>);
 static_assert(!std::contiguous_iterator<const_reverse_iterator>);
 static_assert(!std::indirectly_writable<const_iterator, value_type>);
-static_assert(std::sentinel_for<const_iterator, iterator>);
-static_assert(std::sentinel_for<const_iterator, const_iterator>);
+static_assert( std::sentinel_for<const_iterator, iterator>);
+static_assert( std::sentinel_for<const_iterator, const_iterator>);
 static_assert(!std::sentinel_for<const_iterator, reverse_iterator>);
 static_assert(!std::sentinel_for<const_iterator, const_reverse_iterator>);
-static_assert(std::sized_sentinel_for<const_iterator, iterator>);
-static_assert(std::sized_sentinel_for<const_iterator, const_iterator>);
+static_assert( std::sized_sentinel_for<const_iterator, iterator>);
+static_assert( std::sized_sentinel_for<const_iterator, const_iterator>);
 static_assert(!std::sized_sentinel_for<const_iterator, reverse_iterator>);
 static_assert(!std::sized_sentinel_for<const_iterator, const_reverse_iterator>);
+static_assert( std::indirectly_movable<const_iterator, iterator>);
+static_assert( std::indirectly_movable_storable<const_iterator, iterator>);
+static_assert(!std::indirectly_movable<const_iterator, const_iterator>);
+static_assert(!std::indirectly_movable_storable<const_iterator, const_iterator>);
+static_assert( std::indirectly_movable<const_iterator, reverse_iterator>);
+static_assert( std::indirectly_movable_storable<const_iterator, reverse_iterator>);
+static_assert(!std::indirectly_movable<const_iterator, const_reverse_iterator>);
+static_assert(!std::indirectly_movable_storable<const_iterator, const_reverse_iterator>);

diff  --git a/libcxx/test/std/containers/unord/unord.map/iterator_concept_conformance.compile.pass.cpp b/libcxx/test/std/containers/unord/unord.map/iterator_concept_conformance.compile.pass.cpp
index 8f23959c11815..7f8403029f2d9 100644
--- a/libcxx/test/std/containers/unord/unord.map/iterator_concept_conformance.compile.pass.cpp
+++ b/libcxx/test/std/containers/unord/unord.map/iterator_concept_conformance.compile.pass.cpp
@@ -33,6 +33,8 @@ static_assert(!std::sized_sentinel_for<iterator, iterator>);
 static_assert(!std::sized_sentinel_for<iterator, const_iterator>);
 static_assert(!std::sized_sentinel_for<iterator, local_iterator>);
 static_assert(!std::sized_sentinel_for<iterator, const_local_iterator>);
+static_assert(std::indirectly_movable<iterator, std::pair<int, int>*>);
+static_assert(!std::indirectly_movable_storable<iterator, std::pair<int, int>*>);
 
 static_assert(std::forward_iterator<const_iterator>);
 static_assert(!std::bidirectional_iterator<const_iterator>);
@@ -57,6 +59,8 @@ static_assert(!std::sized_sentinel_for<local_iterator, iterator>);
 static_assert(!std::sized_sentinel_for<local_iterator, const_iterator>);
 static_assert(!std::sized_sentinel_for<local_iterator, local_iterator>);
 static_assert(!std::sized_sentinel_for<local_iterator, const_local_iterator>);
+static_assert(std::indirectly_movable<local_iterator, std::pair<int, int>*>);
+static_assert(!std::indirectly_movable_storable<local_iterator, std::pair<int, int>*>);
 
 static_assert(std::forward_iterator<const_local_iterator>);
 static_assert(!std::bidirectional_iterator<const_local_iterator>);

diff  --git a/libcxx/test/std/containers/unord/unord.multimap/iterator_concept_conformance.compile.pass.cpp b/libcxx/test/std/containers/unord/unord.multimap/iterator_concept_conformance.compile.pass.cpp
index 1b73f1785b2ff..b5afdc11a2f7e 100644
--- a/libcxx/test/std/containers/unord/unord.multimap/iterator_concept_conformance.compile.pass.cpp
+++ b/libcxx/test/std/containers/unord/unord.multimap/iterator_concept_conformance.compile.pass.cpp
@@ -33,6 +33,8 @@ static_assert(!std::sized_sentinel_for<iterator, iterator>);
 static_assert(!std::sized_sentinel_for<iterator, const_iterator>);
 static_assert(!std::sized_sentinel_for<iterator, local_iterator>);
 static_assert(!std::sized_sentinel_for<iterator, const_local_iterator>);
+static_assert(std::indirectly_movable<iterator, std::pair<int, int>*>);
+static_assert(!std::indirectly_movable_storable<iterator, std::pair<int, int>*>);
 
 static_assert(std::forward_iterator<const_iterator>);
 static_assert(!std::bidirectional_iterator<const_iterator>);
@@ -57,6 +59,8 @@ static_assert(!std::sized_sentinel_for<local_iterator, iterator>);
 static_assert(!std::sized_sentinel_for<local_iterator, const_iterator>);
 static_assert(!std::sized_sentinel_for<local_iterator, local_iterator>);
 static_assert(!std::sized_sentinel_for<local_iterator, const_local_iterator>);
+static_assert(std::indirectly_movable<local_iterator, std::pair<int, int>*>);
+static_assert(!std::indirectly_movable_storable<local_iterator, std::pair<int, int>*>);
 
 static_assert(std::forward_iterator<const_local_iterator>);
 static_assert(!std::bidirectional_iterator<const_local_iterator>);

diff  --git a/libcxx/test/std/containers/unord/unord.multiset/iterator_concept_conformance.compile.pass.cpp b/libcxx/test/std/containers/unord/unord.multiset/iterator_concept_conformance.compile.pass.cpp
index 25e25c4493fec..eb318ca19e954 100644
--- a/libcxx/test/std/containers/unord/unord.multiset/iterator_concept_conformance.compile.pass.cpp
+++ b/libcxx/test/std/containers/unord/unord.multiset/iterator_concept_conformance.compile.pass.cpp
@@ -33,6 +33,8 @@ static_assert(!std::sized_sentinel_for<iterator, iterator>);
 static_assert(!std::sized_sentinel_for<iterator, const_iterator>);
 static_assert(!std::sized_sentinel_for<iterator, local_iterator>);
 static_assert(!std::sized_sentinel_for<iterator, const_local_iterator>);
+static_assert(std::indirectly_movable<iterator, int*>);
+static_assert(std::indirectly_movable_storable<iterator, int*>);
 
 static_assert(std::forward_iterator<const_iterator>);
 static_assert(!std::bidirectional_iterator<const_iterator>);
@@ -57,6 +59,8 @@ static_assert(!std::sized_sentinel_for<local_iterator, iterator>);
 static_assert(!std::sized_sentinel_for<local_iterator, const_iterator>);
 static_assert(!std::sized_sentinel_for<local_iterator, local_iterator>);
 static_assert(!std::sized_sentinel_for<local_iterator, const_local_iterator>);
+static_assert(std::indirectly_movable<local_iterator, int*>);
+static_assert(std::indirectly_movable_storable<local_iterator, int*>);
 
 static_assert(std::forward_iterator<const_local_iterator>);
 static_assert(!std::bidirectional_iterator<const_local_iterator>);

diff  --git a/libcxx/test/std/containers/unord/unord.set/iterator_concept_conformance.compile.pass.cpp b/libcxx/test/std/containers/unord/unord.set/iterator_concept_conformance.compile.pass.cpp
index 50426a2a4c37c..db4d5c1159897 100644
--- a/libcxx/test/std/containers/unord/unord.set/iterator_concept_conformance.compile.pass.cpp
+++ b/libcxx/test/std/containers/unord/unord.set/iterator_concept_conformance.compile.pass.cpp
@@ -33,6 +33,8 @@ static_assert(!std::sized_sentinel_for<iterator, iterator>);
 static_assert(!std::sized_sentinel_for<iterator, const_iterator>);
 static_assert(!std::sized_sentinel_for<iterator, local_iterator>);
 static_assert(!std::sized_sentinel_for<iterator, const_local_iterator>);
+static_assert(std::indirectly_movable<iterator, int*>);
+static_assert(std::indirectly_movable_storable<iterator, int*>);
 
 static_assert(std::forward_iterator<const_iterator>);
 static_assert(!std::bidirectional_iterator<const_iterator>);
@@ -56,6 +58,8 @@ static_assert(!std::sized_sentinel_for<local_iterator, iterator>);
 static_assert(!std::sized_sentinel_for<local_iterator, const_iterator>);
 static_assert(!std::sized_sentinel_for<local_iterator, local_iterator>);
 static_assert(!std::sized_sentinel_for<local_iterator, const_local_iterator>);
+static_assert(std::indirectly_movable<local_iterator, int*>);
+static_assert(std::indirectly_movable_storable<local_iterator, int*>);
 
 static_assert(std::forward_iterator<const_local_iterator>);
 static_assert(!std::bidirectional_iterator<const_local_iterator>);

diff  --git a/libcxx/test/std/containers/views/span.iterators/iterator_concept_conformance.compile.pass.cpp b/libcxx/test/std/containers/views/span.iterators/iterator_concept_conformance.compile.pass.cpp
index 80022c2987969..bbbddcd211e33 100644
--- a/libcxx/test/std/containers/views/span.iterators/iterator_concept_conformance.compile.pass.cpp
+++ b/libcxx/test/std/containers/views/span.iterators/iterator_concept_conformance.compile.pass.cpp
@@ -26,3 +26,5 @@ static_assert(std::sentinel_for<iterator, iterator>);
 static_assert(!std::sentinel_for<iterator, reverse_iterator>);
 static_assert(std::sized_sentinel_for<iterator, iterator>);
 static_assert(!std::sized_sentinel_for<iterator, reverse_iterator>);
+static_assert(std::indirectly_movable<iterator, int*>);
+static_assert(std::indirectly_movable_storable<iterator, int*>);

diff  --git a/libcxx/test/std/input.output/filesystems/class.directory_iterator/iterator_concept_conformance.compile.pass.cpp b/libcxx/test/std/input.output/filesystems/class.directory_iterator/iterator_concept_conformance.compile.pass.cpp
index 63ab32c0f0316..1d3016ca9833b 100644
--- a/libcxx/test/std/input.output/filesystems/class.directory_iterator/iterator_concept_conformance.compile.pass.cpp
+++ b/libcxx/test/std/input.output/filesystems/class.directory_iterator/iterator_concept_conformance.compile.pass.cpp
@@ -24,6 +24,8 @@ static_assert(!std::indirectly_writable<fs::directory_iterator, value_type>);
 static_assert(!std::incrementable<fs::directory_iterator>);
 static_assert(std::sentinel_for<fs::directory_iterator, fs::directory_iterator>);
 static_assert(!std::sized_sentinel_for<fs::directory_iterator, fs::directory_iterator>);
+static_assert(!std::indirectly_movable<fs::directory_iterator, fs::directory_iterator>);
+static_assert(!std::indirectly_movable_storable<fs::directory_iterator, fs::directory_iterator>);
 
 static_assert(std::input_iterator<fs::recursive_directory_iterator>);
 static_assert(!std::forward_iterator<fs::recursive_directory_iterator>);
@@ -31,3 +33,5 @@ static_assert(!std::indirectly_writable<fs::recursive_directory_iterator, value_
 static_assert(!std::incrementable<fs::recursive_directory_iterator>);
 static_assert(std::sentinel_for<fs::recursive_directory_iterator, fs::recursive_directory_iterator>);
 static_assert(!std::sized_sentinel_for<fs::recursive_directory_iterator, fs::recursive_directory_iterator>);
+static_assert(!std::indirectly_movable<fs::recursive_directory_iterator, fs::recursive_directory_iterator>);
+static_assert(!std::indirectly_movable_storable<fs::recursive_directory_iterator, fs::recursive_directory_iterator>);

diff  --git a/libcxx/test/std/iterators/iterator.requirements/alg.req.ind.move/indirectly_movable.compile.pass.cpp b/libcxx/test/std/iterators/iterator.requirements/alg.req.ind.move/indirectly_movable.compile.pass.cpp
new file mode 100644
index 0000000000000..fb5b02df4dd3f
--- /dev/null
+++ b/libcxx/test/std/iterators/iterator.requirements/alg.req.ind.move/indirectly_movable.compile.pass.cpp
@@ -0,0 +1,59 @@
+//===----------------------------------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+// UNSUPPORTED: c++03, c++11, c++14, c++17
+// UNSUPPORTED: libcpp-no-concepts
+// UNSUPPORTED: gcc-10
+
+// template<class In, class Out>
+// concept indirectly_movable;
+
+#include <iterator>
+
+#include "test_macros.h"
+
+struct IndirectlyMovableWithInt {
+  int& operator*() const;
+};
+
+struct Empty {};
+
+struct MoveOnly {
+  MoveOnly(MoveOnly&&) = default;
+  MoveOnly(MoveOnly const&) = delete;
+  MoveOnly& operator=(MoveOnly&&) = default;
+  MoveOnly& operator=(MoveOnly const&) = delete;
+  MoveOnly() = default;
+};
+
+template<class T>
+struct PointerTo {
+  using value_type = T;
+  T& operator*() const;
+};
+
+static_assert( std::indirectly_movable<int*, int*>);
+static_assert( std::indirectly_movable<const int*, int *>);
+static_assert(!std::indirectly_movable<int*, const int *>);
+static_assert(!std::indirectly_movable<const int*, const int *>);
+static_assert( std::indirectly_movable<int*, int[2]>);
+static_assert(!std::indirectly_movable<int[2], int*>);
+static_assert(!std::indirectly_movable<int[2], int[2]>);
+static_assert(!std::indirectly_movable<int(&)[2], int(&)[2]>);
+static_assert(!std::indirectly_movable<int, int*>);
+static_assert(!std::indirectly_movable<int, int>);
+static_assert( std::indirectly_movable<Empty*, Empty*>);
+static_assert( std::indirectly_movable<int*, IndirectlyMovableWithInt>);
+static_assert(!std::indirectly_movable<Empty*, IndirectlyMovableWithInt>);
+static_assert( std::indirectly_movable<int*, IndirectlyMovableWithInt>);
+static_assert( std::indirectly_movable<MoveOnly*, MoveOnly*>);
+static_assert(!std::indirectly_movable<MoveOnly*, const MoveOnly*>);
+static_assert(!std::indirectly_movable<const MoveOnly*, const MoveOnly*>);
+static_assert(!std::indirectly_movable<const MoveOnly*, MoveOnly*>);
+static_assert( std::indirectly_movable<PointerTo<MoveOnly>, PointerTo<MoveOnly>>);
+static_assert( std::indirectly_movable<MoveOnly*, PointerTo<MoveOnly>>);

diff  --git a/libcxx/test/std/iterators/iterator.requirements/alg.req.ind.move/indirectly_movable.subsumption.compile.pass.cpp b/libcxx/test/std/iterators/iterator.requirements/alg.req.ind.move/indirectly_movable.subsumption.compile.pass.cpp
new file mode 100644
index 0000000000000..b6c829d5c9752
--- /dev/null
+++ b/libcxx/test/std/iterators/iterator.requirements/alg.req.ind.move/indirectly_movable.subsumption.compile.pass.cpp
@@ -0,0 +1,31 @@
+//===----------------------------------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+// UNSUPPORTED: c++03, c++11, c++14, c++17
+// UNSUPPORTED: libcpp-no-concepts
+// UNSUPPORTED: gcc-10
+
+// template<class In, class Out>
+// concept indirectly_movable;
+
+#include <iterator>
+
+#include <concepts>
+
+template<std::indirectly_readable I, class O>
+constexpr bool indirectly_movable_subsumption() {
+  return false;
+}
+
+template<class I, class O>
+  requires std::indirectly_movable<I, O>
+constexpr bool indirectly_movable_subsumption() {
+  return true;
+}
+
+static_assert(indirectly_movable_subsumption<int*, int*>());

diff  --git a/libcxx/test/std/iterators/iterator.requirements/alg.req.ind.move/indirectly_movable_storable.compile.pass.cpp b/libcxx/test/std/iterators/iterator.requirements/alg.req.ind.move/indirectly_movable_storable.compile.pass.cpp
new file mode 100644
index 0000000000000..16ab3de69aa3d
--- /dev/null
+++ b/libcxx/test/std/iterators/iterator.requirements/alg.req.ind.move/indirectly_movable_storable.compile.pass.cpp
@@ -0,0 +1,143 @@
+//===----------------------------------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+// UNSUPPORTED: c++03, c++11, c++14, c++17
+// UNSUPPORTED: libcpp-no-concepts
+// UNSUPPORTED: gcc-10
+
+// template<class In, class Out>
+// concept indirectly_movable_storable;
+
+#include <iterator>
+
+#include "test_macros.h"
+
+struct Empty {};
+
+struct MoveOnlyConvertible;
+struct AssignableToMoveOnly;
+
+struct MoveOnly {
+  MoveOnly(MoveOnly&&) = default;
+  MoveOnly(MoveOnly const&) = delete;
+  MoveOnly& operator=(MoveOnly&&) = default;
+  MoveOnly& operator=(MoveOnly const&) = delete;
+  MoveOnly() = default;
+
+  MoveOnly& operator=(MoveOnlyConvertible const&) = delete;
+  MoveOnly& operator=(AssignableToMoveOnly const&);
+};
+
+template<class T, class ValueType = T>
+struct PointerTo {
+  using value_type = ValueType;
+  T& operator*() const;
+};
+
+// MoveOnlyConvertible is convertible to MoveOnly, but not assignable to it. This is
+// implemented by explicitly deleting "operator=(MoveOnlyConvertible)" in MoveOnly.
+struct MoveOnlyConvertible {
+  operator MoveOnly&() const;
+};
+
+// This type can be constructed with a MoveOnly and assigned to a MoveOnly, so it does
+// model indirectly_movable_storable.
+struct AssignableToMoveOnly {
+  AssignableToMoveOnly() = default;
+  AssignableToMoveOnly(const MoveOnly&);
+};
+
+struct DeletedMoveCtor {
+  DeletedMoveCtor(DeletedMoveCtor&&) = delete;
+  DeletedMoveCtor& operator=(DeletedMoveCtor&&) = default;
+};
+
+struct CommonType { };
+
+struct NotConstructibleFromRefIn {
+  struct ValueType {
+    operator CommonType&() const;
+  };
+
+  struct ReferenceType {
+    operator CommonType&() const;
+  };
+
+  using value_type = ValueType;
+  ReferenceType& operator*() const;
+};
+
+template <template <class> class X, template <class> class Y>
+struct std::basic_common_reference<NotConstructibleFromRefIn::ValueType,
+                                   NotConstructibleFromRefIn::ReferenceType, X, Y> {
+  using type = CommonType&;
+};
+
+template <template <class> class X, template <class> class Y>
+struct std::basic_common_reference<NotConstructibleFromRefIn::ReferenceType,
+                                   NotConstructibleFromRefIn::ValueType, X, Y> {
+  using type = CommonType&;
+};
+
+struct NotAssignableFromRefIn {
+  struct ReferenceType;
+
+  struct ValueType {
+    ValueType(ReferenceType);
+    ValueType& operator=(ReferenceType) = delete;
+    operator CommonType&() const;
+  };
+
+  struct ReferenceType {
+    operator CommonType&() const;
+  };
+
+  using value_type = ValueType;
+  ReferenceType& operator*() const;
+};
+
+template <template <class> class X, template <class> class Y>
+struct std::basic_common_reference<NotAssignableFromRefIn::ValueType,
+                                   NotAssignableFromRefIn::ReferenceType, X, Y> {
+  using type = CommonType&;
+};
+
+template <template <class> class X, template <class> class Y>
+struct std::basic_common_reference<NotAssignableFromRefIn::ReferenceType,
+                                   NotAssignableFromRefIn::ValueType, X, Y> {
+  using type = CommonType&;
+};
+
+struct AnyWritable {
+  template<class T>
+  AnyWritable& operator=(T&&);
+};
+
+struct AnyOutput {
+  using value_type = AnyWritable;
+  AnyWritable& operator*() const;
+};
+
+static_assert( std::indirectly_movable_storable<int*, int*>);
+static_assert( std::indirectly_movable_storable<const int*, int *>);
+static_assert( std::indirectly_movable_storable<int*, int[2]>);
+static_assert( std::indirectly_movable_storable<Empty*, Empty*>);
+static_assert( std::indirectly_movable_storable<MoveOnly*, MoveOnly*>);
+static_assert( std::indirectly_movable_storable<PointerTo<MoveOnly>, PointerTo<MoveOnly>>);
+// The case when indirectly_writable<iter_rvalue_reference> but not indirectly_writable<iter_value>.
+static_assert( std::indirectly_writable<
+                 PointerTo<MoveOnly, MoveOnlyConvertible>,
+                 std::iter_rvalue_reference_t<
+                    PointerTo<MoveOnly, MoveOnlyConvertible>>>);
+static_assert(!std::indirectly_movable_storable<PointerTo<MoveOnly, MoveOnlyConvertible>,
+                                                PointerTo<MoveOnly, MoveOnlyConvertible>>);
+static_assert(!std::indirectly_movable_storable<DeletedMoveCtor*, DeletedMoveCtor*>);
+static_assert( std::indirectly_movable_storable<PointerTo<MoveOnly, AssignableToMoveOnly>,
+                                                PointerTo<MoveOnly, AssignableToMoveOnly>>);
+static_assert(!std::indirectly_movable_storable<NotConstructibleFromRefIn, AnyOutput>);
+static_assert(!std::indirectly_movable_storable<NotAssignableFromRefIn, AnyOutput>);

diff  --git a/libcxx/test/std/iterators/iterator.requirements/alg.req.ind.move/indirectly_movable_storable.subsumption.compile.pass.cpp b/libcxx/test/std/iterators/iterator.requirements/alg.req.ind.move/indirectly_movable_storable.subsumption.compile.pass.cpp
new file mode 100644
index 0000000000000..845fbc8a4705b
--- /dev/null
+++ b/libcxx/test/std/iterators/iterator.requirements/alg.req.ind.move/indirectly_movable_storable.subsumption.compile.pass.cpp
@@ -0,0 +1,32 @@
+//===----------------------------------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+// UNSUPPORTED: c++03, c++11, c++14, c++17
+// UNSUPPORTED: libcpp-no-concepts
+// UNSUPPORTED: gcc-10
+
+// template<class In, class Out>
+// concept indirectly_movable_storable;
+
+#include <iterator>
+
+#include <concepts>
+
+template<class I, class O>
+  requires std::indirectly_movable<I, O>
+constexpr bool indirectly_movable_storable_subsumption() {
+  return false;
+}
+
+template<class I, class O>
+  requires std::indirectly_movable_storable<I, O>
+constexpr bool indirectly_movable_storable_subsumption() {
+  return true;
+}
+
+static_assert(indirectly_movable_storable_subsumption<int*, int*>());

diff  --git a/libcxx/test/std/iterators/iterator.requirements/alg.req.ind.move/{ind.move.subsumption.compile.pass.cpp} b/libcxx/test/std/iterators/iterator.requirements/alg.req.ind.move/{ind.move.subsumption.compile.pass.cpp}
new file mode 100644
index 0000000000000..e69de29bb2d1d

diff  --git a/libcxx/test/std/iterators/predef.iterators/insert.iterators/back.insert.iterator/iterator_concept_conformance.compile.pass.cpp b/libcxx/test/std/iterators/predef.iterators/insert.iterators/back.insert.iterator/iterator_concept_conformance.compile.pass.cpp
index 429379c08275c..ea04ea8482b22 100644
--- a/libcxx/test/std/iterators/predef.iterators/insert.iterators/back.insert.iterator/iterator_concept_conformance.compile.pass.cpp
+++ b/libcxx/test/std/iterators/predef.iterators/insert.iterators/back.insert.iterator/iterator_concept_conformance.compile.pass.cpp
@@ -24,3 +24,5 @@ static_assert(std::input_or_output_iterator<iterator>);
 static_assert(!std::sentinel_for<iterator, iterator>);
 static_assert(!std::sized_sentinel_for<iterator, iterator>);
 static_assert(!std::input_iterator<iterator>);
+static_assert(std::indirectly_movable<int*, iterator>);
+static_assert(std::indirectly_movable_storable<int*, iterator>);

diff  --git a/libcxx/test/std/iterators/predef.iterators/insert.iterators/front.insert.iterator/iterator_concept_conformance.compile.pass.cpp b/libcxx/test/std/iterators/predef.iterators/insert.iterators/front.insert.iterator/iterator_concept_conformance.compile.pass.cpp
index e061896e5b2d0..13e8b0352baf9 100644
--- a/libcxx/test/std/iterators/predef.iterators/insert.iterators/front.insert.iterator/iterator_concept_conformance.compile.pass.cpp
+++ b/libcxx/test/std/iterators/predef.iterators/insert.iterators/front.insert.iterator/iterator_concept_conformance.compile.pass.cpp
@@ -24,3 +24,5 @@ static_assert(std::input_or_output_iterator<iterator>);
 static_assert(!std::sentinel_for<iterator, iterator>);
 static_assert(!std::sized_sentinel_for<iterator, iterator>);
 static_assert(!std::input_iterator<iterator>);
+static_assert(std::indirectly_movable<int*, iterator>);
+static_assert(std::indirectly_movable_storable<int*, iterator>);

diff  --git a/libcxx/test/std/iterators/predef.iterators/insert.iterators/insert.iterator/iterator_concept_conformance.compile.pass.cpp b/libcxx/test/std/iterators/predef.iterators/insert.iterators/insert.iterator/iterator_concept_conformance.compile.pass.cpp
index b4cdcd0303eaf..b73ca79491474 100644
--- a/libcxx/test/std/iterators/predef.iterators/insert.iterators/insert.iterator/iterator_concept_conformance.compile.pass.cpp
+++ b/libcxx/test/std/iterators/predef.iterators/insert.iterators/insert.iterator/iterator_concept_conformance.compile.pass.cpp
@@ -23,3 +23,5 @@ static_assert(std::weakly_incrementable<iterator>);
 static_assert(std::input_or_output_iterator<iterator>);
 static_assert(!std::sentinel_for<iterator, iterator>);
 static_assert(!std::input_iterator<iterator>);
+static_assert(std::indirectly_movable<int*, iterator>);
+static_assert(std::indirectly_movable_storable<int*, iterator>);

diff  --git a/libcxx/test/std/iterators/predef.iterators/move.iterators/move.iterator/iterator_concept_conformance.compile.pass.cpp b/libcxx/test/std/iterators/predef.iterators/move.iterators/move.iterator/iterator_concept_conformance.compile.pass.cpp
index e239ce10c75b8..bd28036dc6de3 100644
--- a/libcxx/test/std/iterators/predef.iterators/move.iterators/move.iterator/iterator_concept_conformance.compile.pass.cpp
+++ b/libcxx/test/std/iterators/predef.iterators/move.iterators/move.iterator/iterator_concept_conformance.compile.pass.cpp
@@ -23,3 +23,5 @@ static_assert(!std::indirectly_writable<iterator, int>);
 static_assert(std::incrementable<iterator>);
 static_assert(std::sentinel_for<iterator, iterator>);
 static_assert(std::sized_sentinel_for<iterator, iterator>);
+static_assert(!std::indirectly_movable<int*, iterator>);
+static_assert(!std::indirectly_movable_storable<int*, iterator>);

diff  --git a/libcxx/test/std/iterators/predef.iterators/reverse.iterators/iterator_concept_conformance.compile.pass.cpp b/libcxx/test/std/iterators/predef.iterators/reverse.iterators/iterator_concept_conformance.compile.pass.cpp
index 2ad643ae44e39..687d37db30cd8 100644
--- a/libcxx/test/std/iterators/predef.iterators/reverse.iterators/iterator_concept_conformance.compile.pass.cpp
+++ b/libcxx/test/std/iterators/predef.iterators/reverse.iterators/iterator_concept_conformance.compile.pass.cpp
@@ -30,15 +30,21 @@ static_assert(common_reverse_iterator_checks<reverse_bidirectional_iterator>());
 static_assert(std::bidirectional_iterator<reverse_bidirectional_iterator>);
 static_assert(!std::random_access_iterator<reverse_bidirectional_iterator>);
 static_assert(!std::sized_sentinel_for<reverse_bidirectional_iterator, reverse_bidirectional_iterator>);
+static_assert( std::indirectly_movable<reverse_bidirectional_iterator, reverse_bidirectional_iterator>);
+static_assert( std::indirectly_movable_storable<reverse_bidirectional_iterator, reverse_bidirectional_iterator>);
 
 using reverse_random_access_iterator = std::reverse_iterator<random_access_iterator<int*>>;
 static_assert(common_reverse_iterator_checks<reverse_random_access_iterator>());
 static_assert(std::random_access_iterator<reverse_random_access_iterator>);
 static_assert(!std::contiguous_iterator<reverse_random_access_iterator>);
 static_assert(std::sized_sentinel_for<reverse_random_access_iterator, reverse_random_access_iterator>);
+static_assert( std::indirectly_movable<reverse_random_access_iterator, reverse_random_access_iterator>);
+static_assert( std::indirectly_movable_storable<reverse_random_access_iterator, reverse_random_access_iterator>);
 
 using reverse_contiguous_iterator = std::reverse_iterator<contiguous_iterator<int*>>;
 static_assert(common_reverse_iterator_checks<reverse_contiguous_iterator>());
 static_assert(std::random_access_iterator<reverse_contiguous_iterator>);
 static_assert(!std::contiguous_iterator<reverse_contiguous_iterator>);
 static_assert(std::sized_sentinel_for<reverse_contiguous_iterator, reverse_contiguous_iterator>);
+static_assert( std::indirectly_movable<reverse_contiguous_iterator, reverse_contiguous_iterator>);
+static_assert( std::indirectly_movable_storable<reverse_contiguous_iterator, reverse_contiguous_iterator>);

diff  --git a/libcxx/test/std/iterators/stream.iterators/istream.iterator/iterator_concept_conformance.compile.pass.cpp b/libcxx/test/std/iterators/stream.iterators/istream.iterator/iterator_concept_conformance.compile.pass.cpp
index edf9217f0c543..8bb5e94218f42 100644
--- a/libcxx/test/std/iterators/stream.iterators/istream.iterator/iterator_concept_conformance.compile.pass.cpp
+++ b/libcxx/test/std/iterators/stream.iterators/istream.iterator/iterator_concept_conformance.compile.pass.cpp
@@ -24,3 +24,5 @@ static_assert(std::input_or_output_iterator<iterator>);
 static_assert(std::sentinel_for<iterator, iterator>);
 static_assert(!std::sized_sentinel_for<iterator, iterator>);
 static_assert(std::input_iterator<iterator>);
+static_assert(!std::indirectly_movable<int*, iterator>);
+static_assert(!std::indirectly_movable_storable<int*, iterator>);

diff  --git a/libcxx/test/std/iterators/stream.iterators/istreambuf.iterator/iterator_concept_conformance.compile.pass.cpp b/libcxx/test/std/iterators/stream.iterators/istreambuf.iterator/iterator_concept_conformance.compile.pass.cpp
index 765d5b250fc33..2e529ca1fe2a1 100644
--- a/libcxx/test/std/iterators/stream.iterators/istreambuf.iterator/iterator_concept_conformance.compile.pass.cpp
+++ b/libcxx/test/std/iterators/stream.iterators/istreambuf.iterator/iterator_concept_conformance.compile.pass.cpp
@@ -25,3 +25,5 @@ static_assert(!std::indirectly_writable<iterator, char>);
 static_assert(!std::incrementable<iterator>);
 static_assert(std::sentinel_for<iterator, iterator>);
 static_assert(!std::sized_sentinel_for<iterator, iterator>);
+static_assert(std::indirectly_movable<iterator, char*>);
+static_assert(std::indirectly_movable_storable<iterator, char*>);

diff  --git a/libcxx/test/std/iterators/stream.iterators/ostream.iterator/iterator_concept_conformance.compile.pass.cpp b/libcxx/test/std/iterators/stream.iterators/ostream.iterator/iterator_concept_conformance.compile.pass.cpp
index a48e56c4b53ee..068692e637742 100644
--- a/libcxx/test/std/iterators/stream.iterators/ostream.iterator/iterator_concept_conformance.compile.pass.cpp
+++ b/libcxx/test/std/iterators/stream.iterators/ostream.iterator/iterator_concept_conformance.compile.pass.cpp
@@ -24,3 +24,5 @@ static_assert(std::input_or_output_iterator<iterator>);
 static_assert(!std::sentinel_for<iterator, iterator>);
 static_assert(!std::sized_sentinel_for<iterator, iterator>);
 static_assert(!std::input_iterator<iterator>);
+static_assert(std::indirectly_movable<int*, iterator>);
+static_assert(std::indirectly_movable_storable<int*, iterator>);

diff  --git a/libcxx/test/std/iterators/stream.iterators/ostreambuf.iterator/iterator_concept_conformance.compile.pass.cpp b/libcxx/test/std/iterators/stream.iterators/ostreambuf.iterator/iterator_concept_conformance.compile.pass.cpp
index 67672947d2078..2b2d0f9cbdd97 100644
--- a/libcxx/test/std/iterators/stream.iterators/ostreambuf.iterator/iterator_concept_conformance.compile.pass.cpp
+++ b/libcxx/test/std/iterators/stream.iterators/ostreambuf.iterator/iterator_concept_conformance.compile.pass.cpp
@@ -25,3 +25,5 @@ static_assert(std::input_or_output_iterator<iterator>);
 static_assert(!std::sentinel_for<iterator, iterator>);
 static_assert(!std::sized_sentinel_for<iterator, iterator>);
 static_assert(!std::input_iterator<iterator>);
+static_assert(std::indirectly_movable<char*, iterator>);
+static_assert(std::indirectly_movable_storable<char*, iterator>);

diff  --git a/libcxx/test/std/re/re.iter/re.regiter/iterator_concept_conformance.compile.pass.cpp b/libcxx/test/std/re/re.iter/re.regiter/iterator_concept_conformance.compile.pass.cpp
index 74fd8796ef009..7818c475330c6 100644
--- a/libcxx/test/std/re/re.iter/re.regiter/iterator_concept_conformance.compile.pass.cpp
+++ b/libcxx/test/std/re/re.iter/re.regiter/iterator_concept_conformance.compile.pass.cpp
@@ -21,3 +21,5 @@ static_assert(!std::bidirectional_iterator<std::cregex_iterator>);
 static_assert(!std::indirectly_writable<std::cregex_iterator, char>);
 static_assert(std::sentinel_for<std::cregex_iterator, std::cregex_iterator>);
 static_assert(!std::sized_sentinel_for<std::cregex_iterator, std::cregex_iterator>);
+static_assert(!std::indirectly_movable<std::cregex_iterator, std::cregex_iterator>);
+static_assert(!std::indirectly_movable_storable<std::cregex_iterator, std::cregex_iterator>);

diff  --git a/libcxx/test/std/re/re.iter/re.tokiter/iterator_concept_conformance.compile.pass.cpp b/libcxx/test/std/re/re.iter/re.tokiter/iterator_concept_conformance.compile.pass.cpp
index b8de464eb881d..b1ed97a9173b7 100644
--- a/libcxx/test/std/re/re.iter/re.tokiter/iterator_concept_conformance.compile.pass.cpp
+++ b/libcxx/test/std/re/re.iter/re.tokiter/iterator_concept_conformance.compile.pass.cpp
@@ -21,3 +21,5 @@ static_assert(!std::bidirectional_iterator<std::cregex_token_iterator>);
 static_assert(!std::indirectly_writable<std::cregex_token_iterator, char>);
 static_assert(std::sentinel_for<std::cregex_token_iterator, std::cregex_token_iterator>);
 static_assert(!std::sized_sentinel_for<std::cregex_token_iterator, std::cregex_token_iterator>);
+static_assert(!std::indirectly_movable<std::cregex_token_iterator, std::cregex_token_iterator>);
+static_assert(!std::indirectly_movable_storable<std::cregex_token_iterator, std::cregex_token_iterator>);

diff  --git a/libcxx/test/std/strings/basic.string/string.iterators/iterator_concept_conformance.compile.pass.cpp b/libcxx/test/std/strings/basic.string/string.iterators/iterator_concept_conformance.compile.pass.cpp
index f147efac7495a..6efb5ae836b5b 100644
--- a/libcxx/test/std/strings/basic.string/string.iterators/iterator_concept_conformance.compile.pass.cpp
+++ b/libcxx/test/std/strings/basic.string/string.iterators/iterator_concept_conformance.compile.pass.cpp
@@ -32,6 +32,14 @@ static_assert(std::sized_sentinel_for<iterator, iterator>);
 static_assert(std::sized_sentinel_for<iterator, const_iterator>);
 static_assert(!std::sized_sentinel_for<iterator, reverse_iterator>);
 static_assert(!std::sized_sentinel_for<iterator, const_reverse_iterator>);
+static_assert( std::indirectly_movable<iterator, iterator>);
+static_assert( std::indirectly_movable_storable<iterator, iterator>);
+static_assert(!std::indirectly_movable<iterator, const_iterator>);
+static_assert(!std::indirectly_movable_storable<iterator, const_iterator>);
+static_assert( std::indirectly_movable<iterator, reverse_iterator>);
+static_assert( std::indirectly_movable_storable<iterator, reverse_iterator>);
+static_assert(!std::indirectly_movable<iterator, const_reverse_iterator>);
+static_assert(!std::indirectly_movable_storable<iterator, const_reverse_iterator>);
 
 static_assert(std::contiguous_iterator<const_iterator>);
 static_assert(!std::indirectly_writable<const_iterator, value_type>);
@@ -43,3 +51,11 @@ static_assert(std::sized_sentinel_for<const_iterator, iterator>);
 static_assert(std::sized_sentinel_for<const_iterator, const_iterator>);
 static_assert(!std::sized_sentinel_for<const_iterator, reverse_iterator>);
 static_assert(!std::sized_sentinel_for<const_iterator, const_reverse_iterator>);
+static_assert( std::indirectly_movable<const_iterator, iterator>);
+static_assert( std::indirectly_movable_storable<const_iterator, iterator>);
+static_assert(!std::indirectly_movable<const_iterator, const_iterator>);
+static_assert(!std::indirectly_movable_storable<const_iterator, const_iterator>);
+static_assert( std::indirectly_movable<const_iterator, reverse_iterator>);
+static_assert( std::indirectly_movable_storable<const_iterator, reverse_iterator>);
+static_assert(!std::indirectly_movable<const_iterator, const_reverse_iterator>);
+static_assert(!std::indirectly_movable_storable<const_iterator, const_reverse_iterator>);

diff  --git a/libcxx/test/std/strings/string.view/string.view.iterators/iterator_concept_conformance.compile.pass.cpp b/libcxx/test/std/strings/string.view/string.view.iterators/iterator_concept_conformance.compile.pass.cpp
index 53eee4ef80b30..fb12fa84491a1 100644
--- a/libcxx/test/std/strings/string.view/string.view.iterators/iterator_concept_conformance.compile.pass.cpp
+++ b/libcxx/test/std/strings/string.view/string.view.iterators/iterator_concept_conformance.compile.pass.cpp
@@ -31,6 +31,8 @@ static_assert(std::sized_sentinel_for<iterator, iterator>);
 static_assert(std::sized_sentinel_for<iterator, const_iterator>);
 static_assert(!std::sized_sentinel_for<iterator, reverse_iterator>);
 static_assert(!std::sized_sentinel_for<iterator, const_reverse_iterator>);
+static_assert(std::indirectly_movable<iterator, char*>);
+static_assert(std::indirectly_movable_storable<iterator, char*>);
 
 static_assert(std::contiguous_iterator<const_iterator>);
 static_assert(!std::indirectly_writable<const_iterator, char>);

diff  --git a/libcxx/test/std/utilities/memory/unique.ptr/iterator_concept_conformance.compile.pass.cpp b/libcxx/test/std/utilities/memory/unique.ptr/iterator_concept_conformance.compile.pass.cpp
index 3c7df3e89775d..68c06bb8168ff 100644
--- a/libcxx/test/std/utilities/memory/unique.ptr/iterator_concept_conformance.compile.pass.cpp
+++ b/libcxx/test/std/utilities/memory/unique.ptr/iterator_concept_conformance.compile.pass.cpp
@@ -19,7 +19,11 @@
 static_assert(std::indirectly_readable<std::unique_ptr<int> >);
 static_assert(std::indirectly_writable<std::unique_ptr<int>, int>);
 static_assert(!std::weakly_incrementable<std::unique_ptr<int> >);
+static_assert(std::indirectly_movable<std::unique_ptr<int>, std::unique_ptr<int>>);
+static_assert(std::indirectly_movable_storable<std::unique_ptr<int>, std::unique_ptr<int>>);
 
 static_assert(!std::indirectly_readable<std::unique_ptr<void> >);
 static_assert(!std::indirectly_writable<std::unique_ptr<void>, void>);
 static_assert(!std::weakly_incrementable<std::unique_ptr<void> >);
+static_assert(!std::indirectly_movable<std::unique_ptr<void>, std::unique_ptr<void>>);
+static_assert(!std::indirectly_movable_storable<std::unique_ptr<void>, std::unique_ptr<void>>);

diff  --git a/libcxx/test/std/utilities/memory/util.smartptr/util.smartptr.shared/iterator_concept_conformance.compile.pass.cpp b/libcxx/test/std/utilities/memory/util.smartptr/util.smartptr.shared/iterator_concept_conformance.compile.pass.cpp
index 4d75b7bf0d6e5..4fe7710f85ba4 100644
--- a/libcxx/test/std/utilities/memory/util.smartptr/util.smartptr.shared/iterator_concept_conformance.compile.pass.cpp
+++ b/libcxx/test/std/utilities/memory/util.smartptr/util.smartptr.shared/iterator_concept_conformance.compile.pass.cpp
@@ -19,7 +19,11 @@
 static_assert(std::indirectly_readable<std::shared_ptr<int> >);
 static_assert(std::indirectly_writable<std::shared_ptr<int>, int>);
 static_assert(!std::weakly_incrementable<std::shared_ptr<int> >);
+static_assert(std::indirectly_movable<std::shared_ptr<int>, std::shared_ptr<int>>);
+static_assert(std::indirectly_movable_storable<std::shared_ptr<int>, std::shared_ptr<int>>);
 
 static_assert(!std::indirectly_readable<std::shared_ptr<void> >);
 static_assert(!std::indirectly_writable<std::shared_ptr<void>, void>);
 static_assert(!std::weakly_incrementable<std::shared_ptr<void> >);
+static_assert(!std::indirectly_movable<std::shared_ptr<void>, std::shared_ptr<void>>);
+static_assert(!std::indirectly_movable_storable<std::shared_ptr<void>, std::shared_ptr<void>>);

diff  --git a/libcxx/test/std/utilities/optional/iterator_concept_conformance.compile.pass.cpp b/libcxx/test/std/utilities/optional/iterator_concept_conformance.compile.pass.cpp
index 152a4e2a13cc9..899dbedc245de 100644
--- a/libcxx/test/std/utilities/optional/iterator_concept_conformance.compile.pass.cpp
+++ b/libcxx/test/std/utilities/optional/iterator_concept_conformance.compile.pass.cpp
@@ -19,3 +19,5 @@
 static_assert(!std::indirectly_readable<std::optional<int> >);
 static_assert(!std::indirectly_writable<std::optional<int>, int>);
 static_assert(!std::weakly_incrementable<std::optional<int> >);
+static_assert(!std::indirectly_movable<std::optional<int>, std::optional<int>>);
+static_assert(!std::indirectly_movable_storable<std::optional<int>, std::optional<int>>);


        


More information about the libcxx-commits mailing list