[libcxx-commits] [libcxx] fc92488 - [libc++] Assume that __wrap_iter always wraps a fancy pointer.

Arthur O'Dwyer via libcxx-commits libcxx-commits at lists.llvm.org
Mon May 24 14:32:07 PDT 2021


Author: Arthur O'Dwyer
Date: 2021-05-24T17:30:21-04:00
New Revision: fc9248877d07132981f2d598d3684de81d12d0b8

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

LOG: [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

Added: 
    

Modified: 
    libcxx/include/__iterator/iterator_traits.h
    libcxx/include/iterator
    libcxx/test/libcxx/iterators/contiguous_iterators.pass.cpp

Removed: 
    


################################################################################
diff  --git a/libcxx/include/__iterator/iterator_traits.h b/libcxx/include/__iterator/iterator_traits.h
index ebffc974f0e1..307ee143c1d2 100644
--- a/libcxx/include/__iterator/iterator_traits.h
+++ b/libcxx/include/__iterator/iterator_traits.h
@@ -428,7 +428,7 @@ struct _LIBCPP_TEMPLATE_VIS iterator_traits<_Tp*>
 
 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 @@ struct __has_iterator_category_convertible_to<_Tp, _Up, false> : false_type {};
 
 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 @@ struct __is_cpp17_bidirectional_iterator : public __has_iterator_category_conver
 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/libcxx/include/iterator b/libcxx/include/iterator
index 6bc98ecb6774..e3d1360971e7 100644
--- a/libcxx/include/iterator
+++ b/libcxx/include/iterator
@@ -1294,8 +1294,7 @@ public:
     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 @@ private:
 
 #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());
 }

diff  --git a/libcxx/test/libcxx/iterators/contiguous_iterators.pass.cpp b/libcxx/test/libcxx/iterators/contiguous_iterators.pass.cpp
index 06d8c38eb224..8899ffcd3562 100644
--- a/libcxx/test/libcxx/iterators/contiguous_iterators.pass.cpp
+++ b/libcxx/test/libcxx/iterators/contiguous_iterators.pass.cpp
@@ -138,6 +138,21 @@ class my_contiguous_iterator
 };
 #endif
 
+struct fake_deque_iterator : std::deque<int>::iterator {
+    using element_type = int;
+};
+static_assert(std::__is_cpp17_random_access_iterator<fake_deque_iterator>::value, "");
+static_assert(!std::__is_cpp17_contiguous_iterator<fake_deque_iterator>::value, "");
+
+#if TEST_STD_VER >= 20
+struct fake2_deque_iterator : std::deque<int>::iterator {
+    using iterator_concept = std::contiguous_iterator_tag;
+    using element_type = int;
+};
+static_assert(std::__is_cpp17_random_access_iterator<fake2_deque_iterator>::value, "");
+static_assert(std::__is_cpp17_contiguous_iterator<fake2_deque_iterator>::value, "");
+#endif
+
 int main(int, char**)
 {
 //  basic tests
@@ -178,21 +193,19 @@ int main(int, char**)
 
     static_assert(( std::__is_cpp17_contiguous_iterator<std::__wrap_iter<T *> >::value), "");
     static_assert(( std::__is_cpp17_contiguous_iterator<std::__wrap_iter<std::__wrap_iter<T *> > >::value), "");
-    static_assert((!std::__is_cpp17_contiguous_iterator<std::__wrap_iter<std::reverse_iterator<T *> > >::value), "");
 
-    static_assert((!std::__is_cpp17_contiguous_iterator<std::__wrap_iter<my_random_access_iterator> >::value), "");
-    static_assert((!std::__is_cpp17_contiguous_iterator<std::__wrap_iter<std::__wrap_iter<my_random_access_iterator> > >::value), "");
-    static_assert((!std::__is_cpp17_contiguous_iterator<std::__wrap_iter<std::reverse_iterator<my_random_access_iterator> > >::value), "");
+    // Here my_random_access_iterator is standing in for some user's fancy pointer type, written pre-C++20.
+    static_assert(( std::__is_cpp17_contiguous_iterator<std::__wrap_iter<my_random_access_iterator> >::value), "");
+    static_assert(( std::__is_cpp17_contiguous_iterator<std::__wrap_iter<std::__wrap_iter<my_random_access_iterator> > >::value), "");
 
 #if TEST_STD_VER >= 20
     static_assert(( std::__is_cpp17_contiguous_iterator<std::__wrap_iter<my_contiguous_iterator> >::value), "");
     static_assert(( std::__is_cpp17_contiguous_iterator<std::__wrap_iter<std::__wrap_iter<my_contiguous_iterator> > >::value), "");
-    static_assert((!std::__is_cpp17_contiguous_iterator<std::__wrap_iter<std::reverse_iterator<my_contiguous_iterator> > >::value), "");
 #endif
 
 //  iterators in the libc++ test suite
     static_assert((!std::__is_cpp17_contiguous_iterator<output_iterator       <char *> >::value), "");
-    static_assert((!std::__is_cpp17_contiguous_iterator<cpp17_input_iterator        <char *> >::value), "");
+    static_assert((!std::__is_cpp17_contiguous_iterator<cpp17_input_iterator  <char *> >::value), "");
     static_assert((!std::__is_cpp17_contiguous_iterator<forward_iterator      <char *> >::value), "");
     static_assert((!std::__is_cpp17_contiguous_iterator<bidirectional_iterator<char *> >::value), "");
     static_assert((!std::__is_cpp17_contiguous_iterator<random_access_iterator<char *> >::value), "");
@@ -228,14 +241,12 @@ int main(int, char**)
     static_assert((!std::__is_cpp17_contiguous_iterator<std::deque<int>::const_iterator>             ::value), "");
     static_assert((!std::__is_cpp17_contiguous_iterator<std::deque<int>::reverse_iterator>           ::value), "");
     static_assert((!std::__is_cpp17_contiguous_iterator<std::deque<int>::const_reverse_iterator>     ::value), "");
-    static_assert((!std::__is_cpp17_contiguous_iterator<std::__wrap_iter<std::deque<int>::iterator> >::value), "");
 
 //  vector<bool> is random-access but not contiguous
     static_assert((!std::__is_cpp17_contiguous_iterator<std::vector<bool>::iterator>                   ::value), "");
     static_assert((!std::__is_cpp17_contiguous_iterator<std::vector<bool>::const_iterator>             ::value), "");
     static_assert((!std::__is_cpp17_contiguous_iterator<std::vector<bool>::reverse_iterator>           ::value), "");
     static_assert((!std::__is_cpp17_contiguous_iterator<std::vector<bool>::const_reverse_iterator>     ::value), "");
-    static_assert((!std::__is_cpp17_contiguous_iterator<std::__wrap_iter<std::vector<bool>::iterator> >::value), "");
 
 #if TEST_STD_VER >= 11
     static_assert(( std::__is_cpp17_contiguous_iterator<std::initializer_list<int>::iterator>      ::value), "");


        


More information about the libcxx-commits mailing list