- 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
__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 {
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>
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)));
}
}
_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)));
}
}
// 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
>::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));
_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
>::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)
{
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
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;
}
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;
}
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*> >();
#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>*> >();
#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
#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
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;
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;
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;
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_;}