[libcxx][ranges] Add `indirectly_movable` and `indirectly_movable_storable`.
Differential Revision: https://reviews.llvm.org/D102639
NOKEYCHECK=True
GitOrigin-RevId: 075f2370c7fa5495649d09be8b1a9802b17a7f2b
diff --git a/include/__iterator/concepts.h b/include/__iterator/concepts.h
index a654131..95f6891 100644
--- a/include/__iterator/concepts.h
+++ b/include/__iterator/concepts.h
@@ -167,7 +167,6 @@
{ _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 @@
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/include/iterator b/include/iterator
index 08faf4d..929cc16 100644
--- a/include/iterator
+++ b/include/iterator
@@ -125,6 +125,13 @@
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 = ptrdiff_t,
class Pointer = T*, class Reference = T&>
struct iterator // deprecated in C++17
diff --git a/test/std/containers/associative/map/iterator_concept_conformance.compile.pass.cpp b/test/std/containers/associative/map/iterator_concept_conformance.compile.pass.cpp
index c74dcfa..43fa91d 100644
--- a/test/std/containers/associative/map/iterator_concept_conformance.compile.pass.cpp
+++ b/test/std/containers/associative/map/iterator_concept_conformance.compile.pass.cpp
@@ -33,6 +33,8 @@
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/test/std/containers/associative/multimap/iterator_concept_conformance.compile.pass.cpp b/test/std/containers/associative/multimap/iterator_concept_conformance.compile.pass.cpp
index 21a612a..539d01e 100644
--- a/test/std/containers/associative/multimap/iterator_concept_conformance.compile.pass.cpp
+++ b/test/std/containers/associative/multimap/iterator_concept_conformance.compile.pass.cpp
@@ -33,6 +33,8 @@
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/test/std/containers/associative/multiset/iterator_concept_conformance.compile.pass.cpp b/test/std/containers/associative/multiset/iterator_concept_conformance.compile.pass.cpp
index 6c89f2d..0b44c3e 100644
--- a/test/std/containers/associative/multiset/iterator_concept_conformance.compile.pass.cpp
+++ b/test/std/containers/associative/multiset/iterator_concept_conformance.compile.pass.cpp
@@ -33,6 +33,8 @@
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/test/std/containers/associative/set/iterator_concept_conformance.compile.pass.cpp b/test/std/containers/associative/set/iterator_concept_conformance.compile.pass.cpp
index f33771f..76b42fe 100644
--- a/test/std/containers/associative/set/iterator_concept_conformance.compile.pass.cpp
+++ b/test/std/containers/associative/set/iterator_concept_conformance.compile.pass.cpp
@@ -33,6 +33,8 @@
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/test/std/containers/sequences/array/iterator_concept_conformance.compile.pass.cpp b/test/std/containers/sequences/array/iterator_concept_conformance.compile.pass.cpp
index 0987835..29a0f3a 100644
--- a/test/std/containers/sequences/array/iterator_concept_conformance.compile.pass.cpp
+++ b/test/std/containers/sequences/array/iterator_concept_conformance.compile.pass.cpp
@@ -31,6 +31,14 @@
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, 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/test/std/containers/sequences/deque/iterator_concept_conformance.compile.pass.cpp b/test/std/containers/sequences/deque/iterator_concept_conformance.compile.pass.cpp
index 248e34b..1b1bf60 100644
--- a/test/std/containers/sequences/deque/iterator_concept_conformance.compile.pass.cpp
+++ b/test/std/containers/sequences/deque/iterator_concept_conformance.compile.pass.cpp
@@ -33,6 +33,14 @@
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, 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/test/std/containers/sequences/forwardlist/forwardlist.iter/iterator_concept_conformance.compile.pass.cpp b/test/std/containers/sequences/forwardlist/forwardlist.iter/iterator_concept_conformance.compile.pass.cpp
index 6a3edcb..8caa26e 100644
--- a/test/std/containers/sequences/forwardlist/forwardlist.iter/iterator_concept_conformance.compile.pass.cpp
+++ b/test/std/containers/sequences/forwardlist/forwardlist.iter/iterator_concept_conformance.compile.pass.cpp
@@ -27,6 +27,10 @@
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, 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/test/std/containers/sequences/list/iterator_concept_conformance.compile.pass.cpp b/test/std/containers/sequences/list/iterator_concept_conformance.compile.pass.cpp
index fe3e148..2a4ffe5 100644
--- a/test/std/containers/sequences/list/iterator_concept_conformance.compile.pass.cpp
+++ b/test/std/containers/sequences/list/iterator_concept_conformance.compile.pass.cpp
@@ -33,6 +33,14 @@
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, 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/test/std/containers/sequences/vector.bool/iterator_concept_conformance.compile.pass.cpp b/test/std/containers/sequences/vector.bool/iterator_concept_conformance.compile.pass.cpp
index 7f5f87b..037383a 100644
--- a/test/std/containers/sequences/vector.bool/iterator_concept_conformance.compile.pass.cpp
+++ b/test/std/containers/sequences/vector.bool/iterator_concept_conformance.compile.pass.cpp
@@ -22,30 +22,32 @@
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/test/std/containers/sequences/vector/iterator_concept_conformance.compile.pass.cpp b/test/std/containers/sequences/vector/iterator_concept_conformance.compile.pass.cpp
index e1160dc..3af7267 100644
--- a/test/std/containers/sequences/vector/iterator_concept_conformance.compile.pass.cpp
+++ b/test/std/containers/sequences/vector/iterator_concept_conformance.compile.pass.cpp
@@ -22,28 +22,44 @@
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/test/std/containers/unord/unord.map/iterator_concept_conformance.compile.pass.cpp b/test/std/containers/unord/unord.map/iterator_concept_conformance.compile.pass.cpp
index 8f23959..7f84030 100644
--- a/test/std/containers/unord/unord.map/iterator_concept_conformance.compile.pass.cpp
+++ b/test/std/containers/unord/unord.map/iterator_concept_conformance.compile.pass.cpp
@@ -33,6 +33,8 @@
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, 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/test/std/containers/unord/unord.multimap/iterator_concept_conformance.compile.pass.cpp b/test/std/containers/unord/unord.multimap/iterator_concept_conformance.compile.pass.cpp
index 1b73f17..b5afdc1 100644
--- a/test/std/containers/unord/unord.multimap/iterator_concept_conformance.compile.pass.cpp
+++ b/test/std/containers/unord/unord.multimap/iterator_concept_conformance.compile.pass.cpp
@@ -33,6 +33,8 @@
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, 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/test/std/containers/unord/unord.multiset/iterator_concept_conformance.compile.pass.cpp b/test/std/containers/unord/unord.multiset/iterator_concept_conformance.compile.pass.cpp
index 25e25c4..eb318ca 100644
--- a/test/std/containers/unord/unord.multiset/iterator_concept_conformance.compile.pass.cpp
+++ b/test/std/containers/unord/unord.multiset/iterator_concept_conformance.compile.pass.cpp
@@ -33,6 +33,8 @@
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, 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/test/std/containers/unord/unord.set/iterator_concept_conformance.compile.pass.cpp b/test/std/containers/unord/unord.set/iterator_concept_conformance.compile.pass.cpp
index 50426a2..db4d5c1 100644
--- a/test/std/containers/unord/unord.set/iterator_concept_conformance.compile.pass.cpp
+++ b/test/std/containers/unord/unord.set/iterator_concept_conformance.compile.pass.cpp
@@ -33,6 +33,8 @@
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, 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/test/std/containers/views/span.iterators/iterator_concept_conformance.compile.pass.cpp b/test/std/containers/views/span.iterators/iterator_concept_conformance.compile.pass.cpp
index 80022c2..bbbddcd 100644
--- a/test/std/containers/views/span.iterators/iterator_concept_conformance.compile.pass.cpp
+++ b/test/std/containers/views/span.iterators/iterator_concept_conformance.compile.pass.cpp
@@ -26,3 +26,5 @@
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/test/std/input.output/filesystems/class.directory_iterator/iterator_concept_conformance.compile.pass.cpp b/test/std/input.output/filesystems/class.directory_iterator/iterator_concept_conformance.compile.pass.cpp
index 63ab32c..1d3016c 100644
--- a/test/std/input.output/filesystems/class.directory_iterator/iterator_concept_conformance.compile.pass.cpp
+++ b/test/std/input.output/filesystems/class.directory_iterator/iterator_concept_conformance.compile.pass.cpp
@@ -24,6 +24,8 @@
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::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/test/std/iterators/iterator.requirements/alg.req.ind.move/indirectly_movable.compile.pass.cpp b/test/std/iterators/iterator.requirements/alg.req.ind.move/indirectly_movable.compile.pass.cpp
new file mode 100644
index 0000000..fb5b02d
--- /dev/null
+++ b/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/test/std/iterators/iterator.requirements/alg.req.ind.move/indirectly_movable.subsumption.compile.pass.cpp b/test/std/iterators/iterator.requirements/alg.req.ind.move/indirectly_movable.subsumption.compile.pass.cpp
new file mode 100644
index 0000000..b6c829d
--- /dev/null
+++ b/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/test/std/iterators/iterator.requirements/alg.req.ind.move/indirectly_movable_storable.compile.pass.cpp b/test/std/iterators/iterator.requirements/alg.req.ind.move/indirectly_movable_storable.compile.pass.cpp
new file mode 100644
index 0000000..16ab3de
--- /dev/null
+++ b/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/test/std/iterators/iterator.requirements/alg.req.ind.move/indirectly_movable_storable.subsumption.compile.pass.cpp b/test/std/iterators/iterator.requirements/alg.req.ind.move/indirectly_movable_storable.subsumption.compile.pass.cpp
new file mode 100644
index 0000000..845fbc8
--- /dev/null
+++ b/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/test/std/iterators/iterator.requirements/alg.req.ind.move/\173ind.move.subsumption.compile.pass.cpp\175" "b/test/std/iterators/iterator.requirements/alg.req.ind.move/\173ind.move.subsumption.compile.pass.cpp\175"
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ "b/test/std/iterators/iterator.requirements/alg.req.ind.move/\173ind.move.subsumption.compile.pass.cpp\175"
diff --git a/test/std/iterators/predef.iterators/insert.iterators/back.insert.iterator/iterator_concept_conformance.compile.pass.cpp b/test/std/iterators/predef.iterators/insert.iterators/back.insert.iterator/iterator_concept_conformance.compile.pass.cpp
index 429379c..ea04ea8 100644
--- a/test/std/iterators/predef.iterators/insert.iterators/back.insert.iterator/iterator_concept_conformance.compile.pass.cpp
+++ b/test/std/iterators/predef.iterators/insert.iterators/back.insert.iterator/iterator_concept_conformance.compile.pass.cpp
@@ -24,3 +24,5 @@
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/test/std/iterators/predef.iterators/insert.iterators/front.insert.iterator/iterator_concept_conformance.compile.pass.cpp b/test/std/iterators/predef.iterators/insert.iterators/front.insert.iterator/iterator_concept_conformance.compile.pass.cpp
index e061896..13e8b03 100644
--- a/test/std/iterators/predef.iterators/insert.iterators/front.insert.iterator/iterator_concept_conformance.compile.pass.cpp
+++ b/test/std/iterators/predef.iterators/insert.iterators/front.insert.iterator/iterator_concept_conformance.compile.pass.cpp
@@ -24,3 +24,5 @@
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/test/std/iterators/predef.iterators/insert.iterators/insert.iterator/iterator_concept_conformance.compile.pass.cpp b/test/std/iterators/predef.iterators/insert.iterators/insert.iterator/iterator_concept_conformance.compile.pass.cpp
index b4cdcd0..b73ca79 100644
--- a/test/std/iterators/predef.iterators/insert.iterators/insert.iterator/iterator_concept_conformance.compile.pass.cpp
+++ b/test/std/iterators/predef.iterators/insert.iterators/insert.iterator/iterator_concept_conformance.compile.pass.cpp
@@ -23,3 +23,5 @@
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/test/std/iterators/predef.iterators/move.iterators/move.iterator/iterator_concept_conformance.compile.pass.cpp b/test/std/iterators/predef.iterators/move.iterators/move.iterator/iterator_concept_conformance.compile.pass.cpp
index e239ce1..bd28036 100644
--- a/test/std/iterators/predef.iterators/move.iterators/move.iterator/iterator_concept_conformance.compile.pass.cpp
+++ b/test/std/iterators/predef.iterators/move.iterators/move.iterator/iterator_concept_conformance.compile.pass.cpp
@@ -23,3 +23,5 @@
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/test/std/iterators/predef.iterators/reverse.iterators/iterator_concept_conformance.compile.pass.cpp b/test/std/iterators/predef.iterators/reverse.iterators/iterator_concept_conformance.compile.pass.cpp
index 2ad643a..687d37d 100644
--- a/test/std/iterators/predef.iterators/reverse.iterators/iterator_concept_conformance.compile.pass.cpp
+++ b/test/std/iterators/predef.iterators/reverse.iterators/iterator_concept_conformance.compile.pass.cpp
@@ -30,15 +30,21 @@
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/test/std/iterators/stream.iterators/istream.iterator/iterator_concept_conformance.compile.pass.cpp b/test/std/iterators/stream.iterators/istream.iterator/iterator_concept_conformance.compile.pass.cpp
index edf9217..8bb5e94 100644
--- a/test/std/iterators/stream.iterators/istream.iterator/iterator_concept_conformance.compile.pass.cpp
+++ b/test/std/iterators/stream.iterators/istream.iterator/iterator_concept_conformance.compile.pass.cpp
@@ -24,3 +24,5 @@
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/test/std/iterators/stream.iterators/istreambuf.iterator/iterator_concept_conformance.compile.pass.cpp b/test/std/iterators/stream.iterators/istreambuf.iterator/iterator_concept_conformance.compile.pass.cpp
index 765d5b2..2e529ca 100644
--- a/test/std/iterators/stream.iterators/istreambuf.iterator/iterator_concept_conformance.compile.pass.cpp
+++ b/test/std/iterators/stream.iterators/istreambuf.iterator/iterator_concept_conformance.compile.pass.cpp
@@ -25,3 +25,5 @@
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/test/std/iterators/stream.iterators/ostream.iterator/iterator_concept_conformance.compile.pass.cpp b/test/std/iterators/stream.iterators/ostream.iterator/iterator_concept_conformance.compile.pass.cpp
index a48e56c..068692e 100644
--- a/test/std/iterators/stream.iterators/ostream.iterator/iterator_concept_conformance.compile.pass.cpp
+++ b/test/std/iterators/stream.iterators/ostream.iterator/iterator_concept_conformance.compile.pass.cpp
@@ -24,3 +24,5 @@
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/test/std/iterators/stream.iterators/ostreambuf.iterator/iterator_concept_conformance.compile.pass.cpp b/test/std/iterators/stream.iterators/ostreambuf.iterator/iterator_concept_conformance.compile.pass.cpp
index 6767294..2b2d0f9 100644
--- a/test/std/iterators/stream.iterators/ostreambuf.iterator/iterator_concept_conformance.compile.pass.cpp
+++ b/test/std/iterators/stream.iterators/ostreambuf.iterator/iterator_concept_conformance.compile.pass.cpp
@@ -25,3 +25,5 @@
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/test/std/re/re.iter/re.regiter/iterator_concept_conformance.compile.pass.cpp b/test/std/re/re.iter/re.regiter/iterator_concept_conformance.compile.pass.cpp
index 74fd879..7818c47 100644
--- a/test/std/re/re.iter/re.regiter/iterator_concept_conformance.compile.pass.cpp
+++ b/test/std/re/re.iter/re.regiter/iterator_concept_conformance.compile.pass.cpp
@@ -21,3 +21,5 @@
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/test/std/re/re.iter/re.tokiter/iterator_concept_conformance.compile.pass.cpp b/test/std/re/re.iter/re.tokiter/iterator_concept_conformance.compile.pass.cpp
index b8de464..b1ed97a 100644
--- a/test/std/re/re.iter/re.tokiter/iterator_concept_conformance.compile.pass.cpp
+++ b/test/std/re/re.iter/re.tokiter/iterator_concept_conformance.compile.pass.cpp
@@ -21,3 +21,5 @@
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/test/std/strings/basic.string/string.iterators/iterator_concept_conformance.compile.pass.cpp b/test/std/strings/basic.string/string.iterators/iterator_concept_conformance.compile.pass.cpp
index f147efa..6efb5ae 100644
--- a/test/std/strings/basic.string/string.iterators/iterator_concept_conformance.compile.pass.cpp
+++ b/test/std/strings/basic.string/string.iterators/iterator_concept_conformance.compile.pass.cpp
@@ -32,6 +32,14 @@
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, 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/test/std/strings/string.view/string.view.iterators/iterator_concept_conformance.compile.pass.cpp b/test/std/strings/string.view/string.view.iterators/iterator_concept_conformance.compile.pass.cpp
index 53eee4e..fb12fa8 100644
--- a/test/std/strings/string.view/string.view.iterators/iterator_concept_conformance.compile.pass.cpp
+++ b/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, 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/test/std/utilities/memory/unique.ptr/iterator_concept_conformance.compile.pass.cpp b/test/std/utilities/memory/unique.ptr/iterator_concept_conformance.compile.pass.cpp
index 3c7df3e..68c06bb 100644
--- a/test/std/utilities/memory/unique.ptr/iterator_concept_conformance.compile.pass.cpp
+++ b/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/test/std/utilities/memory/util.smartptr/util.smartptr.shared/iterator_concept_conformance.compile.pass.cpp b/test/std/utilities/memory/util.smartptr/util.smartptr.shared/iterator_concept_conformance.compile.pass.cpp
index 4d75b7b..4fe7710 100644
--- a/test/std/utilities/memory/util.smartptr/util.smartptr.shared/iterator_concept_conformance.compile.pass.cpp
+++ b/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/test/std/utilities/optional/iterator_concept_conformance.compile.pass.cpp b/test/std/utilities/optional/iterator_concept_conformance.compile.pass.cpp
index 152a4e2..899dbed 100644
--- a/test/std/utilities/optional/iterator_concept_conformance.compile.pass.cpp
+++ b/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>>);