diff options
author | Arthur O'Dwyer <arthur.j.odwyer@gmail.com> | 2021-01-15 12:59:56 -0500 |
---|---|---|
committer | Arthur O'Dwyer <arthur.j.odwyer@gmail.com> | 2021-02-03 16:28:38 -0500 |
commit | d41c6d51cbadbbd0f81c6ac0d6628d01b881e2a5 (patch) | |
tree | 84e9134754183969eb7397d366d7537fafc0476b /libcxx/include/algorithm | |
parent | 9db61142965e6f4b382e7ff7bde8af5d8396fe98 (diff) | |
download | llvm-d41c6d51cbadbbd0f81c6ac0d6628d01b881e2a5.zip llvm-d41c6d51cbadbbd0f81c6ac0d6628d01b881e2a5.tar.gz llvm-d41c6d51cbadbbd0f81c6ac0d6628d01b881e2a5.tar.bz2 |
[libc++] Rationalize our treatment of contiguous iterators and __unwrap_iter().
- Implement C++20's changes to `reverse_iterator`, so that it won't be
accidentally counted as a contiguous iterator in C++20 mode.
- Implement C++20's changes to `move_iterator` as well.
- `move_iterator` should not be contiguous. This fixes a bug where
we optimized `std::copy`-of-move-iterators in an observable way.
Add a regression test for that bugfix.
- Add libcxx tests for `__is_cpp17_contiguous_iterator` of all relevant
standard iterator types. Particularly check that vector::iterator
is still considered contiguous in all C++ modes, even C++03.
After this patch, there continues to be no supported way to write your
own iterator type in C++17-and-earlier such that libc++ will consider it
"contiguous"; however, we now fully support the C++20 approach (in C++20
mode only). If you want user-defined contiguous iterators in C++17-and-earlier,
libc++'s position is "please upgrade to C++20."
Differential Revision: https://reviews.llvm.org/D94807
Diffstat (limited to 'libcxx/include/algorithm')
-rw-r--r-- | libcxx/include/algorithm | 84 |
1 files changed, 29 insertions, 55 deletions
diff --git a/libcxx/include/algorithm b/libcxx/include/algorithm index 9bc31f8..d8fbac7 100644 --- a/libcxx/include/algorithm +++ b/libcxx/include/algorithm @@ -1639,68 +1639,42 @@ search_n(_ForwardIterator __first, _ForwardIterator __last, _Size __count, const __value_, __equal_to<__v, _Tp>()); } -// copy -template <class _Iter> -inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR -_Iter -__unwrap_iter(_Iter __i) -{ - return __i; -} - -template <class _Tp> -inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR -typename enable_if -< - is_trivially_copy_assignable<_Tp>::value, - _Tp* ->::type -__unwrap_iter(move_iterator<_Tp*> __i) -{ - return __i.base(); -} +// __unwrap_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 +// instantiations and to enable pointer-based optimizations e.g. in std::copy. +// In debug mode, we don't do this. + +template <class _Iter, bool = __is_cpp17_contiguous_iterator<_Iter>::value> +struct __unwrap_iter_impl { + static _LIBCPP_CONSTEXPR _Iter + __apply(_Iter __i) _NOEXCEPT { + return __i; + } +}; #if _LIBCPP_DEBUG_LEVEL < 2 -template <class _Tp> -inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR -typename enable_if -< - is_trivially_copy_assignable<_Tp>::value, - _Tp* ->::type -__unwrap_iter(__wrap_iter<_Tp*> __i) -{ - return __i.base(); -} - -template <class _Tp> -inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR -typename enable_if -< - is_trivially_copy_assignable<_Tp>::value, - const _Tp* ->::type -__unwrap_iter(__wrap_iter<const _Tp*> __i) -{ - return __i.base(); -} +template <class _Iter> +struct __unwrap_iter_impl<_Iter, true> { + static _LIBCPP_CONSTEXPR decltype(_VSTD::__to_address(declval<_Iter>())) + __apply(_Iter __i) _NOEXCEPT { + return _VSTD::__to_address(__i); + } +}; -#else +#endif // _LIBCPP_DEBUG_LEVEL < 2 -template <class _Tp> +template<class _Iter, class _Impl = __unwrap_iter_impl<_Iter> > inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR -typename enable_if -< - is_trivially_copy_assignable<_Tp>::value, - __wrap_iter<_Tp*> ->::type -__unwrap_iter(__wrap_iter<_Tp*> __i) +decltype(_Impl::__apply(_VSTD::declval<_Iter>())) +__unwrap_iter(_Iter __i) _NOEXCEPT { - return __i; + return _Impl::__apply(__i); } -#endif // _LIBCPP_DEBUG_LEVEL < 2 +// copy template <class _InputIterator, class _OutputIterator> inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 @@ -1894,7 +1868,7 @@ inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX14 typename enable_if < is_same<typename remove_const<_Tp>::type, _Up>::value && - is_trivially_copy_assignable<_Up>::value, + is_trivially_move_assignable<_Up>::value, _Up* >::type __move(_Tp* __first, _Tp* __last, _Up* __result) @@ -1942,7 +1916,7 @@ inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX14 typename enable_if < is_same<typename remove_const<_Tp>::type, _Up>::value && - is_trivially_copy_assignable<_Up>::value, + is_trivially_move_assignable<_Up>::value, _Up* >::type __move_backward(_Tp* __first, _Tp* __last, _Up* __result) |