| commit 85167fb7c2920ca8874b197ef397e8e6b9d87c73 |
| Author: Arthur O'Dwyer <arthur.j.odwyer@gmail.com> |
| Date: Wed Feb 3 17:54:13 2021 -0500 |
| |
| [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 |
| |
| 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 @@ public: |
| typedef typename std::iterator_traits<It>::difference_type difference_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_;} |