[libcxx-commits] [libcxx] a9bfb4c - [libc++] Refactor stride_counting_iterator

Louis Dionne via libcxx-commits libcxx-commits at lists.llvm.org
Tue Jan 18 09:24:14 PST 2022


Author: Louis Dionne
Date: 2022-01-18T12:24:05-05:00
New Revision: a9bfb4c4f48d9434918374566d5780c97a805bcc

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

LOG: [libc++] Refactor stride_counting_iterator

Instead of storing the wrapped iterator inside the stride_counting_iterator,
store its base so we can have e.g. a stride_counting_iterator of an
input_iterator (which was previously impossible because input_iterators
are not copyable). Also a few other simplifications in stride_counting_iterator.

As a fly-by fix, remove the member base() functions, which are super
confusing.

Differential Revision: https://reviews.llvm.org/D116613

Added: 
    

Modified: 
    libcxx/test/std/iterators/iterator.primitives/range.iter.ops/range.iter.ops.advance/iterator_sentinel.pass.cpp
    libcxx/test/std/ranges/range.adaptors/range.drop/begin.pass.cpp
    libcxx/test/support/test_iterators.h

Removed: 
    


################################################################################
diff  --git a/libcxx/test/std/iterators/iterator.primitives/range.iter.ops/range.iter.ops.advance/iterator_sentinel.pass.cpp b/libcxx/test/std/iterators/iterator.primitives/range.iter.ops/range.iter.ops.advance/iterator_sentinel.pass.cpp
index 0760572faccbe..3332aa1bc53fc 100644
--- a/libcxx/test/std/iterators/iterator.primitives/range.iter.ops/range.iter.ops.advance/iterator_sentinel.pass.cpp
+++ b/libcxx/test/std/iterators/iterator.primitives/range.iter.ops/range.iter.ops.advance/iterator_sentinel.pass.cpp
@@ -35,7 +35,7 @@ constexpr void check_assignable(int* first, int* last, int* expected) {
     auto it = stride_counting_iterator(It(first));
     auto sent = assignable_sentinel(stride_counting_iterator(It(last)));
     std::ranges::advance(it, sent);
-    assert(base(it.base()) == expected);
+    assert(base(base(it)) == expected);
     assert(it.stride_count() == 0); // because we got here by assigning from last, not by incrementing
   }
 }

diff  --git a/libcxx/test/std/ranges/range.adaptors/range.drop/begin.pass.cpp b/libcxx/test/std/ranges/range.adaptors/range.drop/begin.pass.cpp
index 2455eeeb47f38..9bac2b9fbb218 100644
--- a/libcxx/test/std/ranges/range.adaptors/range.drop/begin.pass.cpp
+++ b/libcxx/test/std/ranges/range.adaptors/range.drop/begin.pass.cpp
@@ -76,9 +76,9 @@ constexpr bool test() {
 
   CountedView view8;
   std::ranges::drop_view dropView8(view8, 5);
-  assert(dropView8.begin().base().base() == globalBuff + 5);
+  assert(base(base(dropView8.begin())) == globalBuff + 5);
   assert(dropView8.begin().stride_count() == 5);
-  assert(dropView8.begin().base().base() == globalBuff + 5);
+  assert(base(base(dropView8.begin())) == globalBuff + 5);
   assert(dropView8.begin().stride_count() == 5);
 
   static_assert(!BeginInvocable<const ForwardView>);

diff  --git a/libcxx/test/support/test_iterators.h b/libcxx/test/support/test_iterators.h
index 36f7caeb5b84e..8bd187df15e67 100644
--- a/libcxx/test/support/test_iterators.h
+++ b/libcxx/test/support/test_iterators.h
@@ -10,6 +10,7 @@
 #define SUPPORT_TEST_ITERATORS_H
 
 #include <cassert>
+#include <concepts>
 #include <iterator>
 #include <stdexcept>
 #include <utility>
@@ -646,39 +647,6 @@ class cpp20_input_iterator
     void operator,(T const &) = delete;
 };
 
-template <std::input_or_output_iterator I>
-struct iterator_concept {
-    using type = std::output_iterator_tag;
-};
-
-template <std::input_iterator I>
-struct iterator_concept<I> {
-    using type = std::input_iterator_tag;
-};
-
-template <std::forward_iterator I>
-struct iterator_concept<I> {
-    using type = std::forward_iterator_tag;
-};
-
-template <std::bidirectional_iterator I>
-struct iterator_concept<I> {
-    using type = std::bidirectional_iterator_tag;
-};
-
-template <std::random_access_iterator I>
-struct iterator_concept<I> {
-    using type = std::random_access_iterator_tag;
-};
-
-template<std::contiguous_iterator I>
-struct iterator_concept<I> {
-    using type = std::contiguous_iterator_tag;
-};
-
-template <std::input_or_output_iterator I>
-using iterator_concept_t = typename iterator_concept<I>::type;
-
 template<std::input_or_output_iterator>
 struct iter_value_or_void { using type = void; };
 
@@ -693,31 +661,37 @@ struct iter_value_or_void<I> {
 // * `stride_displacement`, which records the displacement of the calls. This means that both
 //   op++/op+= will increase the displacement counter by 1, and op--/op-= will decrease the
 //   displacement counter by 1.
-template <std::input_or_output_iterator I>
+template <class It>
 class stride_counting_iterator {
 public:
-    using value_type = typename iter_value_or_void<I>::type;
-    using 
diff erence_type = std::iter_
diff erence_t<I>;
-    using iterator_concept = iterator_concept_t<I>;
-
-    stride_counting_iterator() = default;
+    using value_type = typename iter_value_or_void<It>::type;
+    using 
diff erence_type = std::iter_
diff erence_t<It>;
+    using iterator_concept =
+        std::conditional_t<std::contiguous_iterator<It>,    std::contiguous_iterator_tag,
+        std::conditional_t<std::random_access_iterator<It>, std::random_access_iterator_tag,
+        std::conditional_t<std::bidirectional_iterator<It>, std::bidirectional_iterator_tag,
+        std::conditional_t<std::forward_iterator<It>,       std::forward_iterator_tag,
+        std::conditional_t<std::input_iterator<It>,         std::input_iterator_tag,
+        /* else */                                          std::output_iterator_tag
+    >>>>>;
 
-    constexpr explicit stride_counting_iterator(I current) : base_(std::move(current)) {}
+    stride_counting_iterator() requires std::default_initializable<It> = default;
 
-    constexpr const I& base() const& { return base_; }
+    constexpr explicit stride_counting_iterator(It const& it) : base_(base(it)) { }
 
-    constexpr I base() && { return std::move(base_); }
+    friend constexpr It base(stride_counting_iterator const& it) { return It(it.base_); }
 
     constexpr 
diff erence_type stride_count() const { return stride_count_; }
 
     constexpr 
diff erence_type stride_displacement() const { return stride_displacement_; }
 
-    constexpr decltype(auto) operator*() const { return *base_; }
+    constexpr decltype(auto) operator*() const { return *It(base_); }
 
-    constexpr decltype(auto) operator[](
diff erence_type const n) const { return base_[n]; }
+    constexpr decltype(auto) operator[](
diff erence_type n) const { return It(base_)[n]; }
 
     constexpr stride_counting_iterator& operator++() {
-        ++base_;
+        It tmp(base_);
+        base_ = base(++tmp);
         ++stride_count_;
         ++stride_displacement_;
         return *this;
@@ -726,7 +700,7 @@ class stride_counting_iterator {
     constexpr void operator++(int) { ++*this; }
 
     constexpr stride_counting_iterator operator++(int)
-        requires std::forward_iterator<I>
+        requires std::forward_iterator<It>
     {
         auto temp = *this;
         ++*this;
@@ -734,16 +708,17 @@ class stride_counting_iterator {
     }
 
     constexpr stride_counting_iterator& operator--()
-        requires std::bidirectional_iterator<I>
+        requires std::bidirectional_iterator<It>
     {
-        --base_;
+        It tmp(base_);
+        base_ = base(--tmp);
         ++stride_count_;
         --stride_displacement_;
         return *this;
     }
 
     constexpr stride_counting_iterator operator--(int)
-        requires std::bidirectional_iterator<I>
+        requires std::bidirectional_iterator<It>
     {
         auto temp = *this;
         --*this;
@@ -751,88 +726,84 @@ class stride_counting_iterator {
     }
 
     constexpr stride_counting_iterator& operator+=(
diff erence_type const n)
-        requires std::random_access_iterator<I>
+        requires std::random_access_iterator<It>
     {
-        base_ += n;
+        It tmp(base_);
+        base_ = base(tmp += n);
         ++stride_count_;
         ++stride_displacement_;
         return *this;
     }
 
     constexpr stride_counting_iterator& operator-=(
diff erence_type const n)
-        requires std::random_access_iterator<I>
+        requires std::random_access_iterator<It>
     {
-        base_ -= n;
+        It tmp(base_);
+        base_ = base(tmp -= n);
         ++stride_count_;
         --stride_displacement_;
         return *this;
     }
 
-    friend constexpr stride_counting_iterator operator+(stride_counting_iterator i, 
diff erence_type const n)
-        requires std::random_access_iterator<I>
+    friend constexpr stride_counting_iterator operator+(stride_counting_iterator it, 
diff erence_type n)
+        requires std::random_access_iterator<It>
     {
-        return i += n;
+        return it += n;
     }
 
-    friend constexpr stride_counting_iterator operator+(
diff erence_type const n, stride_counting_iterator i)
-        requires std::random_access_iterator<I>
+    friend constexpr stride_counting_iterator operator+(
diff erence_type n, stride_counting_iterator it)
+        requires std::random_access_iterator<It>
     {
-        return i += n;
+        return it += n;
     }
 
-    friend constexpr stride_counting_iterator operator-(stride_counting_iterator i, 
diff erence_type const n)
-        requires std::random_access_iterator<I>
+    friend constexpr stride_counting_iterator operator-(stride_counting_iterator it, 
diff erence_type n)
+        requires std::random_access_iterator<It>
     {
-        return i -= n;
+        return it -= n;
     }
 
     friend constexpr 
diff erence_type operator-(stride_counting_iterator const& x, stride_counting_iterator const& y)
-        requires std::sized_sentinel_for<I, I>
+        requires std::sized_sentinel_for<It, It>
     {
-        return x.base() - y.base();
+        return base(x) - base(y);
     }
 
     constexpr bool operator==(stride_counting_iterator const& other) const
-        requires std::sentinel_for<I, I>
+        requires std::sentinel_for<It, It>
     {
-        return base_ == other.base_;
-    }
-
-    template <std::sentinel_for<I> S>
-    constexpr bool operator==(S const last) const
-    {
-        return base_ == last;
+        return It(base_) == It(other.base_);
     }
 
     friend constexpr bool operator<(stride_counting_iterator const& x, stride_counting_iterator const& y)
-        requires std::random_access_iterator<I>
+        requires std::random_access_iterator<It>
     {
-        return x.base_ < y.base_;
+        return It(x.base_) < It(y.base_);
     }
 
     friend constexpr bool operator>(stride_counting_iterator const& x, stride_counting_iterator const& y)
-        requires std::random_access_iterator<I>
+        requires std::random_access_iterator<It>
     {
-        return y < x;
+        return It(x.base_) > It(y.base_);
     }
 
     friend constexpr bool operator<=(stride_counting_iterator const& x, stride_counting_iterator const& y)
-        requires std::random_access_iterator<I>
+        requires std::random_access_iterator<It>
     {
-        return !(y < x);
+        return It(x.base_) <= It(y.base_);
     }
 
     friend constexpr bool operator>=(stride_counting_iterator const& x, stride_counting_iterator const& y)
-        requires std::random_access_iterator<I>
+        requires std::random_access_iterator<It>
     {
-        return !(x < y);
+        return It(x.base_) >= It(y.base_);
     }
 
     template <class T>
     void operator,(T const &) = delete;
 
 private:
-    I base_;
+    decltype(base(std::declval<It>())) base_;
     
diff erence_type stride_count_ = 0;
     
diff erence_type stride_displacement_ = 0;
 };


        


More information about the libcxx-commits mailing list