[libc++] Assume that __wrap_iter always wraps a fancy pointer.
Not only do we conscientiously avoid using `__wrap_iter` for non-contiguous
iterators (in vector, string, span...) but also we make the assumption
(in regex) that `__wrap_iter<_Iter>` is contiguous for all `_Iter`.
So `__wrap_iter<reverse_iterator<int*>>` should be considered IFNDR,
and every `__wrap_iter` should correctly advertise contiguity in C++20.
Drive-by simplify some type traits.
Reviewed as part of https://reviews.llvm.org/D102781
NOKEYCHECK=True
GitOrigin-RevId: fc9248877d07132981f2d598d3684de81d12d0b8
diff --git a/include/__iterator/iterator_traits.h b/include/__iterator/iterator_traits.h
index ebffc97..307ee14 100644
--- a/include/__iterator/iterator_traits.h
+++ b/include/__iterator/iterator_traits.h
@@ -428,7 +428,7 @@
template <class _Tp, class _Up, bool = __has_iterator_category<iterator_traits<_Tp> >::value>
struct __has_iterator_category_convertible_to
- : _BoolConstant<is_convertible<typename iterator_traits<_Tp>::iterator_category, _Up>::value>
+ : is_convertible<typename iterator_traits<_Tp>::iterator_category, _Up>
{};
template <class _Tp, class _Up>
@@ -436,7 +436,7 @@
template <class _Tp, class _Up, bool = __has_iterator_concept<_Tp>::value>
struct __has_iterator_concept_convertible_to
- : _BoolConstant<is_convertible<typename _Tp::iterator_concept, _Up>::value>
+ : is_convertible<typename _Tp::iterator_concept, _Up>
{};
template <class _Tp, class _Up>
@@ -454,10 +454,12 @@
template <class _Tp>
struct __is_cpp17_random_access_iterator : public __has_iterator_category_convertible_to<_Tp, random_access_iterator_tag> {};
-// __is_cpp17_contiguous_iterator determines if an iterator is contiguous,
-// either because it advertises itself as such (in C++20) or because it
-// is a pointer type or a known trivial wrapper around a pointer type,
-// such as __wrap_iter<T*>.
+// __is_cpp17_contiguous_iterator determines if an iterator is known by
+// libc++ to be contiguous, either because it advertises itself as such
+// (in C++20) or because it is a pointer type or a known trivial wrapper
+// around a (possibly fancy) pointer type, such as __wrap_iter<T*>.
+// Such iterators receive special "contiguous" optimizations in
+// std::copy and std::sort.
//
#if _LIBCPP_STD_VER > 17
template <class _Tp>
diff --git a/include/iterator b/include/iterator
index 6bc98ec..e3d1360 100644
--- a/include/iterator
+++ b/include/iterator
@@ -1294,8 +1294,7 @@
typedef typename iterator_traits<iterator_type>::reference reference;
typedef typename iterator_traits<iterator_type>::iterator_category iterator_category;
#if _LIBCPP_STD_VER > 17
- typedef _If<__is_cpp17_contiguous_iterator<_Iter>::value,
- contiguous_iterator_tag, iterator_category> iterator_concept;
+ typedef contiguous_iterator_tag iterator_concept;
#endif
private:
@@ -1473,12 +1472,12 @@
#if _LIBCPP_STD_VER <= 17
template <class _It>
-struct __is_cpp17_contiguous_iterator<__wrap_iter<_It> > : __is_cpp17_contiguous_iterator<_It> {};
+struct __is_cpp17_contiguous_iterator<__wrap_iter<_It> > : true_type {};
#endif
template <class _Iter>
_LIBCPP_CONSTEXPR
-_EnableIf<__is_cpp17_contiguous_iterator<_Iter>::value, decltype(_VSTD::__to_address(declval<_Iter>()))>
+decltype(_VSTD::__to_address(declval<_Iter>()))
__to_address(__wrap_iter<_Iter> __w) _NOEXCEPT {
return _VSTD::__to_address(__w.base());
}