Browse Source

fix: caching and typedefs

Sam Jaffe 2 năm trước cách đây
mục cha
commit
55afc0e493

+ 2 - 2
include/iterator/detail/arrow_proxy.h

@@ -18,8 +18,8 @@ template <typename Value> struct value_proxy {
     return *this;
   }
 
-  operator Value &() const { return value; }
-  Value & get() const { return value; }
+  operator Value const &() const { return value; }
+  Value const & get() const { return value; }
 
   Value value;
 };

+ 4 - 0
include/iterator/detail/traits.h

@@ -33,4 +33,8 @@ template <typename C>
 struct is_container<C, void_t<iter<C>>> : std::true_type {};
 
 template <typename C> constexpr bool is_container_v = is_container<C>{};
+
+template <typename Iter>
+constexpr bool is_rvalue_iterator_v =
+    !std::is_reference_v<decltype(*std::declval<Iter>())>;
 }

+ 0 - 1
include/iterator/end_aware_iterator.hpp

@@ -21,7 +21,6 @@ namespace iterator {
 template <typename It>
 class end_aware_iterator : public facade<end_aware_iterator<It>> {
 public:
-  using value_type = typename It::value_type;
   struct sentinel_type {};
   static constexpr sentinel_type sentinel;
 

+ 1 - 1
include/iterator/filter_iterator.hpp

@@ -16,7 +16,7 @@
 
 namespace iterator {
 template <typename Iter, bool Cache>
-class filter_iterator : public facade<filter_iterator<Iter>> {
+class filter_iterator : public facade<filter_iterator<Iter, Cache>> {
 public:
   using reference = typename std::iterator_traits<Iter>::reference;
   using cache_t = std::conditional_t<Cache, detail::value_proxy<reference>,

+ 98 - 46
include/iterator/join_iterator.hpp

@@ -15,79 +15,131 @@
 #include <iterator/facade.h>
 #include <iterator/iterator_fwd.hpp>
 
-namespace iterator {
-template <typename MetaIterator>
-class joining_iterator : public facade<joining_iterator<MetaIterator>> {
-public:
-  using join_iter = MetaIterator;
-  using joinable_type = typename join_iter::value_type;
-  using iter_type = decltype(std::begin(*std::declval<join_iter>()));
+namespace iterator::joining {
+template <typename Iter, typename = void>
+class iterator {
+protected:
+  using inner_t = decltype(*std::declval<Iter>());
 
-  using value_type = typename std::iterator_traits<iter_type>::value_type;
-  using reference = typename std::iterator_traits<iter_type>::reference;
-  using pointer = typename std::iterator_traits<iter_type>::pointer;
-  using difference_type =
-      typename std::iterator_traits<iter_type>::difference_type;
-  using iterator_category = std::forward_iterator_tag;
-
-public:
-  explicit joining_iterator() = default;
+protected:
+  iterator() = default;
 
   template <typename I>
-  joining_iterator(joining_iterator<I> const & other)
-      : joiner_(other.join_iterator()), iterator_(other.element_iterator()) {}
+  iterator(iterator<I> const & other)
+      : iterator(other.join_iterator(), other.element_iterator()) {}
 
   template <typename C, typename = std::enable_if_t<detail::is_container_v<C>>>
-  joining_iterator(C && container)
-      : joining_iterator(end_aware_iterator(std::forward<C>(container))) {}
-
-  joining_iterator(end_aware_iterator<join_iter> join)
-      : joining_iterator(join, {}, true) {}
-
-  joining_iterator(end_aware_iterator<join_iter> join,
-                   end_aware_iterator<iter_type> elem, bool update = false)
-      : joiner_(join), iterator_(elem) {
+  iterator(C && container)
+      : iterator(end_aware_iterator(std::forward<C>(container))) {}
+
+  iterator(end_aware_iterator<Iter> join) : iterator(join, {}, true) {}
+  
+  iterator(end_aware_iterator<Iter> join,
+           end_aware_iterator<iter<inner_t>> elem, bool update = false)
+      : joiner_(join), element_(elem) {
     if (update) { update_iterator(); }
   }
 
-  void increment() {
-    if ((iterator_++).at_end()) {
+  void update_iterator() {
+    while (!joiner_.at_end() &&
+           (element_ = end_aware_iterator(*joiner_)).at_end()) {
       ++joiner_;
-      update_iterator();
     }
   }
 
-  decltype(auto) dereference() const { return *iterator_; }
+protected:
+  end_aware_iterator<Iter> joiner_;
+  end_aware_iterator<iter<inner_t>> element_;
+};
 
-  bool equal_to(joining_iterator const & other) const {
-    return joiner_ == other.joiner_ && iterator_ == other.iterator_;
+template <typename Iter>
+class iterator<Iter, std::enable_if_t<detail::is_rvalue_iterator_v<Iter>>> {
+protected:
+  using inner_t = decltype(*std::declval<Iter>());
+
+protected:
+  iterator() = default;
+  template <typename C, typename = std::enable_if_t<detail::is_container_v<C>>>
+  iterator(C && container) : joiner_(std::forward<C>(container)) {
+    update_iterator();
   }
 
-  end_aware_iterator<join_iter> join_iterator() const { return joiner_; }
-  end_aware_iterator<iter_type> element_iterator() const { return iterator_; }
+  iterator(end_aware_iterator<Iter> join) : joiner_(join) {
+    update_iterator();
+  }
 
-private:
+  iterator(iterator const &other) { *this = other; }
+  iterator(iterator &&other) { *this = std::move(other); }
+  
+  iterator &operator=(iterator const &other) {
+    joiner_ = other.joiner_;
+    sync(std::distance(end_aware_iterator(cache_.get()), element_));
+    return *this;
+  }
+  
+  iterator &operator=(iterator &&other) {
+    joiner_ = std::move(joiner_);
+    sync(std::distance(end_aware_iterator(cache_.get()), element_));
+    return *this;
+  }
+  
   void update_iterator() {
-    while (!joiner_.at_end() && end_aware_iterator(*joiner_).at_end()) {
+    while (!joiner_.at_end() && sync().at_end()) {
       ++joiner_;
     }
-    if (!joiner_.at_end()) {
-      cache_ = *joiner_;
-      iterator_ = end_aware_iterator(cache_.get());
+  }
+  
+private:
+  end_aware_iterator<iter<inner_t>> const & sync(size_t n = 0) {
+    if (joiner_.at_end()) { return element_ = {}; }
+    cache_ = *joiner_;
+    element_ = end_aware_iterator(cache_.get());
+    std::advance(element_, n);
+    return element_;
+  }
+
+protected:
+  end_aware_iterator<Iter> joiner_;
+  detail::value_proxy<decltype(*std::declval<Iter>())> cache_;
+  end_aware_iterator<iter<inner_t>> element_;
+};
+}
+
+namespace iterator {
+template <typename Iter>
+class joining_iterator : public facade<joining_iterator<Iter>>, public joining::iterator<Iter> {
+public:
+  using super_t = joining::iterator<Iter>;
+  
+public:
+  using super_t::super_t;
+  
+  template <typename C, typename = std::enable_if_t<detail::is_container_v<C>>>
+  joining_iterator(C && container) : super_t(std::forward<C>(container)) {}
+
+  joining_iterator(end_aware_iterator<Iter> join) : super_t(join) {}
+  
+  void increment() {
+    if ((++super_t::element_).at_end()) {
+      ++super_t::joiner_;
+      super_t::update_iterator();
     }
   }
 
-  end_aware_iterator<join_iter> joiner_;
-  detail::value_proxy<decltype(*std::declval<join_iter>())> cache_;
-  end_aware_iterator<iter_type> iterator_;
+  decltype(auto) dereference() const { return *super_t::element_; }
+
+  bool equal_to(joining_iterator const & other) const {
+    return join_iterator() == other.join_iterator() &&
+        element_iterator() == other.element_iterator();
+  }
+  
+  auto const &join_iterator() const { return super_t::joiner_; }
+  auto const &element_iterator() const { return super_t::element_; }
 };
 
 template <typename C> joining_iterator(C &&) -> joining_iterator<iter<C>>;
 template <typename JI>
 joining_iterator(end_aware_iterator<JI>) -> joining_iterator<JI>;
-template <typename JI, typename IT>
-joining_iterator(end_aware_iterator<JI>, end_aware_iterator<IT>)
-    -> joining_iterator<JI>;
 }
 
 MAKE_ITERATOR_FACADE_TYPEDEFS_T(::iterator::joining_iterator);