[libcxx-commits] [libcxx] 85167fb - [libc++] Further improve the contiguous-iterator story, and fix some bugs.

Arthur O'Dwyer via libcxx-commits libcxx-commits at lists.llvm.org
Fri Feb 5 12:18:44 PST 2021


Author: Arthur O'Dwyer
Date: 2021-02-05T15:18:04-05:00
New Revision: 85167fb7c2920ca8874b197ef397e8e6b9d87c73

URL: https://github.com/llvm/llvm-project/commit/85167fb7c2920ca8874b197ef397e8e6b9d87c73
DIFF: https://github.com/llvm/llvm-project/commit/85167fb7c2920ca8874b197ef397e8e6b9d87c73.diff

LOG: [libc++] Further improve the contiguous-iterator story, and fix some bugs.

- Quality-of-implementation: Avoid calling __unwrap_iter in constexpr contexts.
    The user might conceivably write a contiguous iterator where normal iterator
    arithmetic is constexpr-friendly but `std::to_address(it)` isn't.

- Bugfix: When you pass contiguous iterators to `std::copy`, you should get
    back your contiguous iterator type, not a raw pointer. That means that
    libc++ can't `__unwrap_iter` unless it also does `__rewrap_iter`.
    Fortunately, this is implementable.

- Improve test coverage of the new `contiguous_iterator` test iterator.
    This catches the bug described above.

- Tests: Stop testing that we can `std::copy` //into// an `input_iterator`.
    Our test iterators may currently support that, but it seems nonsensical to me.

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

Added: 
    

Modified: 
    libcxx/include/algorithm
    libcxx/test/std/algorithms/alg.modifying.operations/alg.copy/copy.pass.cpp
    libcxx/test/std/algorithms/alg.modifying.operations/alg.copy/copy_backward.pass.cpp
    libcxx/test/std/algorithms/alg.modifying.operations/alg.move/move.pass.cpp
    libcxx/test/std/algorithms/alg.modifying.operations/alg.move/move_backward.pass.cpp
    libcxx/test/std/algorithms/alg.sorting/alg.sort/sort/sort_constexpr.pass.cpp
    libcxx/test/std/algorithms/alg.sorting/alg.sort/sort/sort_constexpr_comp.pass.cpp
    libcxx/test/support/test_iterators.h

Removed: 
    


################################################################################
diff  --git a/libcxx/include/algorithm b/libcxx/include/algorithm
index 04126a1f4836..4c139296a816 100644
--- a/libcxx/include/algorithm
+++ b/libcxx/include/algorithm
@@ -1639,12 +1639,22 @@ search_n(_ForwardIterator __first, _ForwardIterator __last, _Size __count, const
                            __value_, __equal_to<__v, _Tp>());
 }
 
-// __unwrap_iter
+// __unwrap_iter, __rewrap_iter
 
-// The job of __unwrap_iter is to lower iterators-that-are-tantamount-to-pointers
-// (such as vector<T>::iterator) into pointers, to reduce the number of template
+// The job of __unwrap_iter is to lower contiguous iterators (such as
+// vector<T>::iterator) into pointers, to reduce the number of template
 // instantiations and to enable pointer-based optimizations e.g. in std::copy.
+// For iterators that are not contiguous, it must be a no-op.
 // In debug mode, we don't do this.
+//
+// __unwrap_iter is non-constexpr for user-defined iterators whose
+// `to_address` and/or `operator->` is non-constexpr. This is okay; but we
+// try to avoid doing __unwrap_iter in constant-evaluated contexts anyway.
+//
+// Some algorithms (e.g. std::copy, but not std::sort) need to convert an
+// "unwrapped" result back into a contiguous iterator. Since contiguous iterators
+// are random-access, we can do this portably using iterator arithmetic; this
+// is the job of __rewrap_iter.
 
 template <class _Iter, bool = __is_cpp17_contiguous_iterator<_Iter>::value>
 struct __unwrap_iter_impl {
@@ -1674,6 +1684,20 @@ __unwrap_iter(_Iter __i) _NOEXCEPT
     return _Impl::__apply(__i);
 }
 
+template<class _OrigIter>
+_OrigIter __rewrap_iter(_OrigIter, _OrigIter __result)
+{
+    return __result;
+}
+
+template<class _OrigIter, class _UnwrappedIter>
+_OrigIter __rewrap_iter(_OrigIter __first, _UnwrappedIter __result)
+{
+    // Precondition: __result is reachable from __first
+    // Precondition: _OrigIter is a contiguous iterator
+    return __first + (__result - _VSTD::__unwrap_iter(__first));
+}
+
 // copy
 
 template <class _InputIterator, class _OutputIterator>
@@ -1716,11 +1740,12 @@ _OutputIterator
 copy(_InputIterator __first, _InputIterator __last, _OutputIterator __result)
 {
     if (__libcpp_is_constant_evaluated()) {
-        return _VSTD::__copy_constexpr(
-            _VSTD::__unwrap_iter(__first), _VSTD::__unwrap_iter(__last), _VSTD::__unwrap_iter(__result));
+        return _VSTD::__copy_constexpr(__first, __last, __result);
     } else {
-        return _VSTD::__copy(
-            _VSTD::__unwrap_iter(__first), _VSTD::__unwrap_iter(__last), _VSTD::__unwrap_iter(__result));
+        return _VSTD::__rewrap_iter(__result,
+            _VSTD::__copy(_VSTD::__unwrap_iter(__first),
+                          _VSTD::__unwrap_iter(__last),
+                          _VSTD::__unwrap_iter(__result)));
     }
 }
 
@@ -1770,13 +1795,12 @@ copy_backward(_BidirectionalIterator1 __first, _BidirectionalIterator1 __last,
               _BidirectionalIterator2 __result)
 {
     if (__libcpp_is_constant_evaluated()) {
-        return _VSTD::__copy_backward_constexpr(_VSTD::__unwrap_iter(__first),
-                                                _VSTD::__unwrap_iter(__last),
-                                                _VSTD::__unwrap_iter(__result));
+        return _VSTD::__copy_backward_constexpr(__first, __last, __result);
     } else {
-        return _VSTD::__copy_backward(_VSTD::__unwrap_iter(__first),
-                                      _VSTD::__unwrap_iter(__last),
-                                      _VSTD::__unwrap_iter(__result));
+        return _VSTD::__rewrap_iter(__result,
+            _VSTD::__copy_backward(_VSTD::__unwrap_iter(__first),
+                                   _VSTD::__unwrap_iter(__last),
+                                   _VSTD::__unwrap_iter(__result)));
     }
 }
 
@@ -1843,8 +1867,6 @@ copy_n(_InputIterator __first, _Size __orig_n, _OutputIterator __result)
 
 // move
 
-// __move_constexpr exists so that __move doesn't call itself when delegating to the constexpr
-// version of __move.
 template <class _InputIterator, class _OutputIterator>
 inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX14
 _OutputIterator
@@ -1873,8 +1895,6 @@ typename enable_if
 >::type
 __move(_Tp* __first, _Tp* __last, _Up* __result)
 {
-    if (__libcpp_is_constant_evaluated())
-        return _VSTD::__move_constexpr(__first, __last, __result);
     const size_t __n = static_cast<size_t>(__last - __first);
     if (__n > 0)
         _VSTD::memmove(__result, __first, __n * sizeof(_Up));
@@ -1886,13 +1906,18 @@ inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17
 _OutputIterator
 move(_InputIterator __first, _InputIterator __last, _OutputIterator __result)
 {
-    return _VSTD::__move(_VSTD::__unwrap_iter(__first), _VSTD::__unwrap_iter(__last), _VSTD::__unwrap_iter(__result));
+    if (__libcpp_is_constant_evaluated()) {
+        return _VSTD::__move_constexpr(__first, __last, __result);
+    } else {
+        return _VSTD::__rewrap_iter(__result,
+            _VSTD::__move(_VSTD::__unwrap_iter(__first),
+                          _VSTD::__unwrap_iter(__last),
+                          _VSTD::__unwrap_iter(__result)));
+    }
 }
 
 // move_backward
 
-// __move_backward_constexpr exists so that __move_backward doesn't call itself when delegating to
-// the constexpr version of __move_backward.
 template <class _InputIterator, class _OutputIterator>
 inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX14
 _OutputIterator
@@ -1921,8 +1946,6 @@ typename enable_if
 >::type
 __move_backward(_Tp* __first, _Tp* __last, _Up* __result)
 {
-    if (__libcpp_is_constant_evaluated())
-        return _VSTD::__move_backward_constexpr(__first, __last, __result);
     const size_t __n = static_cast<size_t>(__last - __first);
     if (__n > 0)
     {
@@ -1938,7 +1961,14 @@ _BidirectionalIterator2
 move_backward(_BidirectionalIterator1 __first, _BidirectionalIterator1 __last,
               _BidirectionalIterator2 __result)
 {
-    return _VSTD::__move_backward(_VSTD::__unwrap_iter(__first), _VSTD::__unwrap_iter(__last), _VSTD::__unwrap_iter(__result));
+    if (__libcpp_is_constant_evaluated()) {
+        return _VSTD::__move_backward_constexpr(__first, __last, __result);
+    } else {
+        return _VSTD::__rewrap_iter(__result,
+            _VSTD::__move_backward(_VSTD::__unwrap_iter(__first),
+                                   _VSTD::__unwrap_iter(__last),
+                                   _VSTD::__unwrap_iter(__result)));
+    }
 }
 
 // iter_swap

diff  --git a/libcxx/test/std/algorithms/alg.modifying.operations/alg.copy/copy.pass.cpp b/libcxx/test/std/algorithms/alg.modifying.operations/alg.copy/copy.pass.cpp
index 32c42b6caf3a..b8d880d09526 100644
--- a/libcxx/test/std/algorithms/alg.modifying.operations/alg.copy/copy.pass.cpp
+++ b/libcxx/test/std/algorithms/alg.modifying.operations/alg.copy/copy.pass.cpp
@@ -40,40 +40,49 @@ TEST_CONSTEXPR_CXX20 bool
 test()
 {
     test_copy<input_iterator<const int*>, output_iterator<int*> >();
-    test_copy<input_iterator<const int*>, input_iterator<int*> >();
     test_copy<input_iterator<const int*>, forward_iterator<int*> >();
     test_copy<input_iterator<const int*>, bidirectional_iterator<int*> >();
     test_copy<input_iterator<const int*>, random_access_iterator<int*> >();
     test_copy<input_iterator<const int*>, int*>();
 
     test_copy<forward_iterator<const int*>, output_iterator<int*> >();
-    test_copy<forward_iterator<const int*>, input_iterator<int*> >();
     test_copy<forward_iterator<const int*>, forward_iterator<int*> >();
     test_copy<forward_iterator<const int*>, bidirectional_iterator<int*> >();
     test_copy<forward_iterator<const int*>, random_access_iterator<int*> >();
     test_copy<forward_iterator<const int*>, int*>();
 
     test_copy<bidirectional_iterator<const int*>, output_iterator<int*> >();
-    test_copy<bidirectional_iterator<const int*>, input_iterator<int*> >();
     test_copy<bidirectional_iterator<const int*>, forward_iterator<int*> >();
     test_copy<bidirectional_iterator<const int*>, bidirectional_iterator<int*> >();
     test_copy<bidirectional_iterator<const int*>, random_access_iterator<int*> >();
     test_copy<bidirectional_iterator<const int*>, int*>();
 
     test_copy<random_access_iterator<const int*>, output_iterator<int*> >();
-    test_copy<random_access_iterator<const int*>, input_iterator<int*> >();
     test_copy<random_access_iterator<const int*>, forward_iterator<int*> >();
     test_copy<random_access_iterator<const int*>, bidirectional_iterator<int*> >();
     test_copy<random_access_iterator<const int*>, random_access_iterator<int*> >();
     test_copy<random_access_iterator<const int*>, int*>();
 
     test_copy<const int*, output_iterator<int*> >();
-    test_copy<const int*, input_iterator<int*> >();
     test_copy<const int*, forward_iterator<int*> >();
     test_copy<const int*, bidirectional_iterator<int*> >();
     test_copy<const int*, random_access_iterator<int*> >();
     test_copy<const int*, int*>();
 
+#if TEST_STD_VER > 17
+    test_copy<input_iterator<const int*>, contiguous_iterator<int*>>();
+    test_copy<forward_iterator<const int*>, contiguous_iterator<int*>>();
+    test_copy<bidirectional_iterator<const int*>, contiguous_iterator<int*>>();
+    test_copy<random_access_iterator<const int*>, contiguous_iterator<int*>>();
+    test_copy<const int*, contiguous_iterator<int*>>();
+
+    test_copy<contiguous_iterator<const int*>, output_iterator<int*>>();
+    test_copy<contiguous_iterator<const int*>, forward_iterator<int*>>();
+    test_copy<contiguous_iterator<const int*>, bidirectional_iterator<int*>>();
+    test_copy<contiguous_iterator<const int*>, random_access_iterator<int*>>();
+    test_copy<contiguous_iterator<const int*>, int*>();
+#endif
+
   return true;
 }
 

diff  --git a/libcxx/test/std/algorithms/alg.modifying.operations/alg.copy/copy_backward.pass.cpp b/libcxx/test/std/algorithms/alg.modifying.operations/alg.copy/copy_backward.pass.cpp
index 6f1743cb221a..78dda56b8b94 100644
--- a/libcxx/test/std/algorithms/alg.modifying.operations/alg.copy/copy_backward.pass.cpp
+++ b/libcxx/test/std/algorithms/alg.modifying.operations/alg.copy/copy_backward.pass.cpp
@@ -53,6 +53,17 @@ test()
     test_copy_backward<const int*, random_access_iterator<int*> >();
     test_copy_backward<const int*, int*>();
 
+#if TEST_STD_VER > 17
+    test_copy_backward<contiguous_iterator<const int*>, bidirectional_iterator<int*>>();
+    test_copy_backward<contiguous_iterator<const int*>, random_access_iterator<int*>>();
+    test_copy_backward<contiguous_iterator<const int*>, int*>();
+
+    test_copy_backward<bidirectional_iterator<const int*>, contiguous_iterator<int*>>();
+    test_copy_backward<random_access_iterator<const int*>, contiguous_iterator<int*>>();
+    test_copy_backward<contiguous_iterator<const int*>, contiguous_iterator<int*>>();
+    test_copy_backward<const int*, contiguous_iterator<int*>>();
+#endif
+
     return true;
 }
 

diff  --git a/libcxx/test/std/algorithms/alg.modifying.operations/alg.move/move.pass.cpp b/libcxx/test/std/algorithms/alg.modifying.operations/alg.move/move.pass.cpp
index 44a075f5306c..ca65631956b3 100644
--- a/libcxx/test/std/algorithms/alg.modifying.operations/alg.move/move.pass.cpp
+++ b/libcxx/test/std/algorithms/alg.modifying.operations/alg.move/move.pass.cpp
@@ -64,35 +64,30 @@ test1()
 int main(int, char**)
 {
     test<input_iterator<const int*>, output_iterator<int*> >();
-    test<input_iterator<const int*>, input_iterator<int*> >();
     test<input_iterator<const int*>, forward_iterator<int*> >();
     test<input_iterator<const int*>, bidirectional_iterator<int*> >();
     test<input_iterator<const int*>, random_access_iterator<int*> >();
     test<input_iterator<const int*>, int*>();
 
     test<forward_iterator<const int*>, output_iterator<int*> >();
-    test<forward_iterator<const int*>, input_iterator<int*> >();
     test<forward_iterator<const int*>, forward_iterator<int*> >();
     test<forward_iterator<const int*>, bidirectional_iterator<int*> >();
     test<forward_iterator<const int*>, random_access_iterator<int*> >();
     test<forward_iterator<const int*>, int*>();
 
     test<bidirectional_iterator<const int*>, output_iterator<int*> >();
-    test<bidirectional_iterator<const int*>, input_iterator<int*> >();
     test<bidirectional_iterator<const int*>, forward_iterator<int*> >();
     test<bidirectional_iterator<const int*>, bidirectional_iterator<int*> >();
     test<bidirectional_iterator<const int*>, random_access_iterator<int*> >();
     test<bidirectional_iterator<const int*>, int*>();
 
     test<random_access_iterator<const int*>, output_iterator<int*> >();
-    test<random_access_iterator<const int*>, input_iterator<int*> >();
     test<random_access_iterator<const int*>, forward_iterator<int*> >();
     test<random_access_iterator<const int*>, bidirectional_iterator<int*> >();
     test<random_access_iterator<const int*>, random_access_iterator<int*> >();
     test<random_access_iterator<const int*>, int*>();
 
     test<const int*, output_iterator<int*> >();
-    test<const int*, input_iterator<int*> >();
     test<const int*, forward_iterator<int*> >();
     test<const int*, bidirectional_iterator<int*> >();
     test<const int*, random_access_iterator<int*> >();
@@ -100,35 +95,30 @@ int main(int, char**)
 
 #if TEST_STD_VER >= 11
     test1<input_iterator<std::unique_ptr<int>*>, output_iterator<std::unique_ptr<int>*> >();
-    test1<input_iterator<std::unique_ptr<int>*>, input_iterator<std::unique_ptr<int>*> >();
     test1<input_iterator<std::unique_ptr<int>*>, forward_iterator<std::unique_ptr<int>*> >();
     test1<input_iterator<std::unique_ptr<int>*>, bidirectional_iterator<std::unique_ptr<int>*> >();
     test1<input_iterator<std::unique_ptr<int>*>, random_access_iterator<std::unique_ptr<int>*> >();
     test1<input_iterator<std::unique_ptr<int>*>, std::unique_ptr<int>*>();
 
     test1<forward_iterator<std::unique_ptr<int>*>, output_iterator<std::unique_ptr<int>*> >();
-    test1<forward_iterator<std::unique_ptr<int>*>, input_iterator<std::unique_ptr<int>*> >();
     test1<forward_iterator<std::unique_ptr<int>*>, forward_iterator<std::unique_ptr<int>*> >();
     test1<forward_iterator<std::unique_ptr<int>*>, bidirectional_iterator<std::unique_ptr<int>*> >();
     test1<forward_iterator<std::unique_ptr<int>*>, random_access_iterator<std::unique_ptr<int>*> >();
     test1<forward_iterator<std::unique_ptr<int>*>, std::unique_ptr<int>*>();
 
     test1<bidirectional_iterator<std::unique_ptr<int>*>, output_iterator<std::unique_ptr<int>*> >();
-    test1<bidirectional_iterator<std::unique_ptr<int>*>, input_iterator<std::unique_ptr<int>*> >();
     test1<bidirectional_iterator<std::unique_ptr<int>*>, forward_iterator<std::unique_ptr<int>*> >();
     test1<bidirectional_iterator<std::unique_ptr<int>*>, bidirectional_iterator<std::unique_ptr<int>*> >();
     test1<bidirectional_iterator<std::unique_ptr<int>*>, random_access_iterator<std::unique_ptr<int>*> >();
     test1<bidirectional_iterator<std::unique_ptr<int>*>, std::unique_ptr<int>*>();
 
     test1<random_access_iterator<std::unique_ptr<int>*>, output_iterator<std::unique_ptr<int>*> >();
-    test1<random_access_iterator<std::unique_ptr<int>*>, input_iterator<std::unique_ptr<int>*> >();
     test1<random_access_iterator<std::unique_ptr<int>*>, forward_iterator<std::unique_ptr<int>*> >();
     test1<random_access_iterator<std::unique_ptr<int>*>, bidirectional_iterator<std::unique_ptr<int>*> >();
     test1<random_access_iterator<std::unique_ptr<int>*>, random_access_iterator<std::unique_ptr<int>*> >();
     test1<random_access_iterator<std::unique_ptr<int>*>, std::unique_ptr<int>*>();
 
     test1<std::unique_ptr<int>*, output_iterator<std::unique_ptr<int>*> >();
-    test1<std::unique_ptr<int>*, input_iterator<std::unique_ptr<int>*> >();
     test1<std::unique_ptr<int>*, forward_iterator<std::unique_ptr<int>*> >();
     test1<std::unique_ptr<int>*, bidirectional_iterator<std::unique_ptr<int>*> >();
     test1<std::unique_ptr<int>*, random_access_iterator<std::unique_ptr<int>*> >();
@@ -136,34 +126,70 @@ int main(int, char**)
 #endif // TEST_STD_VER >= 11
 
 #if TEST_STD_VER > 17
+    test<input_iterator<const int*>, contiguous_iterator<int*>>();
+    test<forward_iterator<const int*>, contiguous_iterator<int*>>();
+    test<bidirectional_iterator<const int*>, contiguous_iterator<int*>>();
+    test<random_access_iterator<const int*>, contiguous_iterator<int*>>();
+    test<const int*, contiguous_iterator<int*>>();
+    test<contiguous_iterator<const int*>, output_iterator<int*>>();
+    test<contiguous_iterator<const int*>, forward_iterator<int*>>();
+    test<contiguous_iterator<const int*>, bidirectional_iterator<int*>>();
+    test<contiguous_iterator<const int*>, random_access_iterator<int*>>();
+    test<contiguous_iterator<const int*>, int*>();
+    test<contiguous_iterator<const int*>, contiguous_iterator<int*>>();
+
+    test1<input_iterator<std::unique_ptr<int>*>, contiguous_iterator<std::unique_ptr<int>*>>();
+    test1<forward_iterator<std::unique_ptr<int>*>, contiguous_iterator<std::unique_ptr<int>*>>();
+    test1<bidirectional_iterator<std::unique_ptr<int>*>, contiguous_iterator<std::unique_ptr<int>*>>();
+    test1<random_access_iterator<std::unique_ptr<int>*>, contiguous_iterator<std::unique_ptr<int>*>>();
+    test1<std::unique_ptr<int>*, contiguous_iterator<std::unique_ptr<int>*>>();
+    test1<contiguous_iterator<std::unique_ptr<int>*>, output_iterator<std::unique_ptr<int>*>>();
+    test1<contiguous_iterator<std::unique_ptr<int>*>, forward_iterator<std::unique_ptr<int>*>>();
+    test1<contiguous_iterator<std::unique_ptr<int>*>, bidirectional_iterator<std::unique_ptr<int>*>>();
+    test1<contiguous_iterator<std::unique_ptr<int>*>, random_access_iterator<std::unique_ptr<int>*>>();
+    test1<contiguous_iterator<std::unique_ptr<int>*>, std::unique_ptr<int>*>();
+    test1<contiguous_iterator<std::unique_ptr<int>*>, contiguous_iterator<std::unique_ptr<int>*>>();
+
     static_assert(test<input_iterator<const int*>, input_iterator<int*> >());
     static_assert(test<input_iterator<const int*>, forward_iterator<int*> >());
     static_assert(test<input_iterator<const int*>, bidirectional_iterator<int*> >());
     static_assert(test<input_iterator<const int*>, random_access_iterator<int*> >());
+    static_assert(test<input_iterator<const int*>, contiguous_iterator<int*> >());
     static_assert(test<input_iterator<const int*>, int*>());
 
     static_assert(test<forward_iterator<const int*>, input_iterator<int*> >());
     static_assert(test<forward_iterator<const int*>, forward_iterator<int*> >());
     static_assert(test<forward_iterator<const int*>, bidirectional_iterator<int*> >());
     static_assert(test<forward_iterator<const int*>, random_access_iterator<int*> >());
+    static_assert(test<forward_iterator<const int*>, contiguous_iterator<int*> >());
     static_assert(test<forward_iterator<const int*>, int*>());
 
     static_assert(test<bidirectional_iterator<const int*>, input_iterator<int*> >());
     static_assert(test<bidirectional_iterator<const int*>, forward_iterator<int*> >());
     static_assert(test<bidirectional_iterator<const int*>, bidirectional_iterator<int*> >());
     static_assert(test<bidirectional_iterator<const int*>, random_access_iterator<int*> >());
+    static_assert(test<bidirectional_iterator<const int*>, contiguous_iterator<int*> >());
     static_assert(test<bidirectional_iterator<const int*>, int*>());
 
     static_assert(test<random_access_iterator<const int*>, input_iterator<int*> >());
     static_assert(test<random_access_iterator<const int*>, forward_iterator<int*> >());
     static_assert(test<random_access_iterator<const int*>, bidirectional_iterator<int*> >());
     static_assert(test<random_access_iterator<const int*>, random_access_iterator<int*> >());
+    static_assert(test<random_access_iterator<const int*>, contiguous_iterator<int*> >());
     static_assert(test<random_access_iterator<const int*>, int*>());
 
+    static_assert(test<contiguous_iterator<const int*>, input_iterator<int*> >());
+    static_assert(test<contiguous_iterator<const int*>, forward_iterator<int*> >());
+    static_assert(test<contiguous_iterator<const int*>, bidirectional_iterator<int*> >());
+    static_assert(test<contiguous_iterator<const int*>, random_access_iterator<int*> >());
+    static_assert(test<contiguous_iterator<const int*>, contiguous_iterator<int*> >());
+    static_assert(test<contiguous_iterator<const int*>, int*>());
+
     static_assert(test<const int*, input_iterator<int*> >());
     static_assert(test<const int*, forward_iterator<int*> >());
     static_assert(test<const int*, bidirectional_iterator<int*> >());
     static_assert(test<const int*, random_access_iterator<int*> >());
+    static_assert(test<const int*, contiguous_iterator<int*> >());
     static_assert(test<const int*, int*>());
 #endif  // TEST_STD_VER > 17
 

diff  --git a/libcxx/test/std/algorithms/alg.modifying.operations/alg.move/move_backward.pass.cpp b/libcxx/test/std/algorithms/alg.modifying.operations/alg.move/move_backward.pass.cpp
index ec7371c6d24c..2e43cd20b148 100644
--- a/libcxx/test/std/algorithms/alg.modifying.operations/alg.move/move_backward.pass.cpp
+++ b/libcxx/test/std/algorithms/alg.modifying.operations/alg.move/move_backward.pass.cpp
@@ -89,16 +89,40 @@ int main(int, char**)
 #endif // TEST_STD_VER >= 11
 
 #if TEST_STD_VER > 17
+    test<bidirectional_iterator<const int*>, contiguous_iterator<int*>>();
+    test<random_access_iterator<const int*>, contiguous_iterator<int*>>();
+    test<const int*, contiguous_iterator<int*>>();
+    test<contiguous_iterator<const int*>, bidirectional_iterator<int*>>();
+    test<contiguous_iterator<const int*>, random_access_iterator<int*>>();
+    test<contiguous_iterator<const int*>, int*>();
+    test<contiguous_iterator<const int*>, contiguous_iterator<int*>>();
+
+    test1<bidirectional_iterator<std::unique_ptr<int>*>, contiguous_iterator<std::unique_ptr<int>*>>();
+    test1<random_access_iterator<std::unique_ptr<int>*>, contiguous_iterator<std::unique_ptr<int>*>>();
+    test1<std::unique_ptr<int>*, contiguous_iterator<std::unique_ptr<int>*>>();
+    test1<contiguous_iterator<std::unique_ptr<int>*>, bidirectional_iterator<std::unique_ptr<int>*>>();
+    test1<contiguous_iterator<std::unique_ptr<int>*>, random_access_iterator<std::unique_ptr<int>*>>();
+    test1<contiguous_iterator<std::unique_ptr<int>*>, std::unique_ptr<int>*>();
+    test1<contiguous_iterator<std::unique_ptr<int>*>, contiguous_iterator<std::unique_ptr<int>*>>();
+
     static_assert(test<bidirectional_iterator<const int*>, bidirectional_iterator<int*> >());
     static_assert(test<bidirectional_iterator<const int*>, random_access_iterator<int*> >());
+    static_assert(test<bidirectional_iterator<const int*>, contiguous_iterator<int*> >());
     static_assert(test<bidirectional_iterator<const int*>, int*>());
 
     static_assert(test<random_access_iterator<const int*>, bidirectional_iterator<int*> >());
     static_assert(test<random_access_iterator<const int*>, random_access_iterator<int*> >());
+    static_assert(test<random_access_iterator<const int*>, contiguous_iterator<int*> >());
     static_assert(test<random_access_iterator<const int*>, int*>());
 
+    static_assert(test<contiguous_iterator<const int*>, bidirectional_iterator<int*> >());
+    static_assert(test<contiguous_iterator<const int*>, random_access_iterator<int*> >());
+    static_assert(test<contiguous_iterator<const int*>, contiguous_iterator<int*> >());
+    static_assert(test<contiguous_iterator<const int*>, int*>());
+
     static_assert(test<const int*, bidirectional_iterator<int*> >());
     static_assert(test<const int*, random_access_iterator<int*> >());
+    static_assert(test<const int*, contiguous_iterator<int*> >());
     static_assert(test<const int*, int*>());
 #endif  // TEST_STD_VER > 17
 

diff  --git a/libcxx/test/std/algorithms/alg.sorting/alg.sort/sort/sort_constexpr.pass.cpp b/libcxx/test/std/algorithms/alg.sorting/alg.sort/sort/sort_constexpr.pass.cpp
index 41ea82cc4845..d719f002351d 100644
--- a/libcxx/test/std/algorithms/alg.sorting/alg.sort/sort/sort_constexpr.pass.cpp
+++ b/libcxx/test/std/algorithms/alg.sorting/alg.sort/sort/sort_constexpr.pass.cpp
@@ -79,22 +79,37 @@ int main(int, char**)
     test_pointers<17, int, random_access_iterator<int**> >();
 
 #if TEST_STD_VER >= 20
+    test<7, int, contiguous_iterator<int*>>();
+    test<257, int, contiguous_iterator<int*>>();
+    test<7, MoveOnly, contiguous_iterator<MoveOnly*>>();
+    test<257, MoveOnly, contiguous_iterator<MoveOnly*>>();
+    test_pointers<17, char, contiguous_iterator<char**>>();
+    test_pointers<17, const char, contiguous_iterator<const char**>>();
+    test_pointers<17, int, contiguous_iterator<int**>>();
+
     static_assert(test<7, int, int*>());
     static_assert(test<7, int, random_access_iterator<int*>>());
+    static_assert(test<7, int, contiguous_iterator<int*>>());
     static_assert(test<257, int, int*>());
     static_assert(test<257, int, random_access_iterator<int*>>());
+    static_assert(test<257, int, contiguous_iterator<int*>>());
 
     static_assert(test<7, MoveOnly, MoveOnly*>());
     static_assert(test<7, MoveOnly, random_access_iterator<MoveOnly*>>());
+    static_assert(test<7, MoveOnly, contiguous_iterator<MoveOnly*>>());
     static_assert(test<257, MoveOnly, MoveOnly*>());
     static_assert(test<257, MoveOnly, random_access_iterator<MoveOnly*>>());
+    static_assert(test<257, MoveOnly, contiguous_iterator<MoveOnly*>>());
 
     static_assert(test_pointers<17, char, char**>());
     static_assert(test_pointers<17, char, random_access_iterator<char**>>());
+    static_assert(test_pointers<17, char, contiguous_iterator<char**>>());
     static_assert(test_pointers<17, const char, const char**>());
     static_assert(test_pointers<17, const char, random_access_iterator<const char**>>());
+    static_assert(test_pointers<17, const char, contiguous_iterator<const char**>>());
     static_assert(test_pointers<17, int, int**>());
     static_assert(test_pointers<17, int, random_access_iterator<int**>>());
+    static_assert(test_pointers<17, int, contiguous_iterator<int**>>());
 #endif
 
     return 0;

diff  --git a/libcxx/test/std/algorithms/alg.sorting/alg.sort/sort/sort_constexpr_comp.pass.cpp b/libcxx/test/std/algorithms/alg.sorting/alg.sort/sort/sort_constexpr_comp.pass.cpp
index 48f057ab8a7f..bfdefedb7f34 100644
--- a/libcxx/test/std/algorithms/alg.sorting/alg.sort/sort/sort_constexpr_comp.pass.cpp
+++ b/libcxx/test/std/algorithms/alg.sorting/alg.sort/sort/sort_constexpr_comp.pass.cpp
@@ -80,22 +80,37 @@ int main(int, char**)
     test_pointers<17, int, random_access_iterator<int**> >();
 
 #if TEST_STD_VER >= 20
+    test<7, int, contiguous_iterator<int*>>();
+    test<257, int, contiguous_iterator<int*>>();
+    test<7, MoveOnly, contiguous_iterator<MoveOnly*>>();
+    test<257, MoveOnly, contiguous_iterator<MoveOnly*>>();
+    test_pointers<17, char, contiguous_iterator<char**>>();
+    test_pointers<17, const char, contiguous_iterator<const char**>>();
+    test_pointers<17, int, contiguous_iterator<int**>>();
+
     static_assert(test<7, int, int*>());
     static_assert(test<7, int, random_access_iterator<int*>>());
+    static_assert(test<7, int, contiguous_iterator<int*>>());
     static_assert(test<257, int, int*>());
     static_assert(test<257, int, random_access_iterator<int*>>());
+    static_assert(test<257, int, contiguous_iterator<int*>>());
 
     static_assert(test<7, MoveOnly, MoveOnly*>());
     static_assert(test<7, MoveOnly, random_access_iterator<MoveOnly*>>());
+    static_assert(test<7, MoveOnly, contiguous_iterator<MoveOnly*>>());
     static_assert(test<257, MoveOnly, MoveOnly*>());
     static_assert(test<257, MoveOnly, random_access_iterator<MoveOnly*>>());
+    static_assert(test<257, MoveOnly, contiguous_iterator<MoveOnly*>>());
 
     static_assert(test_pointers<17, char, char**>());
     static_assert(test_pointers<17, char, random_access_iterator<char**>>());
+    static_assert(test_pointers<17, char, contiguous_iterator<char**>>());
     static_assert(test_pointers<17, const char, const char**>());
     static_assert(test_pointers<17, const char, random_access_iterator<const char**>>());
+    static_assert(test_pointers<17, const char, contiguous_iterator<const char**>>());
     static_assert(test_pointers<17, int, int**>());
     static_assert(test_pointers<17, int, random_access_iterator<int**>>());
+    static_assert(test_pointers<17, int, contiguous_iterator<int**>>());
 #endif
 
     return 0;

diff  --git a/libcxx/test/support/test_iterators.h b/libcxx/test/support/test_iterators.h
index 71ef2d58628b..7ada4bb36553 100644
--- a/libcxx/test/support/test_iterators.h
+++ b/libcxx/test/support/test_iterators.h
@@ -315,6 +315,8 @@ operator-(const random_access_iterator<T>& x, const random_access_iterator<U>& y
 template <class It>
 class contiguous_iterator
 {
+    static_assert(std::is_pointer_v<It>, "Things probably break in this case");
+
     It it_;
 
     template <class U> friend class contiguous_iterator;
@@ -324,14 +326,14 @@ class contiguous_iterator
     typedef typename std::iterator_traits<It>::
diff erence_type 
diff erence_type;
     typedef It                                                 pointer;
     typedef typename std::iterator_traits<It>::reference       reference;
-    typedef typename std::iterator_traits<It>::value_type      element_type;
+    typedef typename std::remove_pointer<It>::type             element_type;
 
     TEST_CONSTEXPR_CXX14 It base() const {return it_;}
 
     TEST_CONSTEXPR_CXX14 contiguous_iterator() : it_() {}
     explicit TEST_CONSTEXPR_CXX14 contiguous_iterator(It it) : it_(it) {}
     template <class U>
-        TEST_CONSTEXPR_CXX14 contiguous_iterator(const contiguous_iterator<U>& u) :it_(u.it_) {}
+        TEST_CONSTEXPR_CXX14 contiguous_iterator(const contiguous_iterator<U>& u) : it_(u.it_) {}
 
     TEST_CONSTEXPR_CXX14 reference operator*() const {return *it_;}
     TEST_CONSTEXPR_CXX14 pointer operator->() const {return it_;}


        


More information about the libcxx-commits mailing list