瀏覽代碼

refactor: add caching option to filter iterator

Sam Jaffe 2 年之前
父節點
當前提交
997fcebc50
共有 3 個文件被更改,包括 41 次插入6 次删除
  1. 27 0
      include/iterator/detail/arrow_proxy.h
  2. 13 5
      include/iterator/filter_iterator.hpp
  3. 1 1
      include/iterator/iterator_fwd.hpp

+ 27 - 0
include/iterator/detail/arrow_proxy.h

@@ -11,4 +11,31 @@ template <typename Reference> struct arrow_proxy {
 };
 
 template <typename R> arrow_proxy(R r) -> arrow_proxy<R>;
+
+template <typename Value> struct value_proxy {
+  value_proxy operator=(Value && value) {
+    this->value = std::move(value);
+    return *this;
+  }
+
+  operator Value &() const { return value; }
+  Value value;
+};
+
+template <typename Value> struct value_proxy<Value &> {
+  value_proxy operator=(Value & value) {
+    this->value = &value;
+    return *this;
+  }
+  operator Value &() const { return *value; }
+
+  Value * value;
+};
+
+struct ignore_proxy {
+  template <typename Value> decltype(auto) operator=(Value && value) {
+    return std::forward<Value>(value);
+  }
+};
+
 }

+ 13 - 5
include/iterator/filter_iterator.hpp

@@ -15,11 +15,13 @@
 #include <iterator/iterator_fwd.hpp>
 
 namespace iterator {
-template <typename Iter>
+template <typename Iter, bool Cache>
 class filter_iterator : public facade<filter_iterator<Iter>> {
 public:
-  using value_type = std::decay_t<decltype(*std::declval<Iter>())>;
-  using predicate_t = std::function<bool(value_type const &)>;
+  using reference = typename std::iterator_traits<Iter>::reference;
+  using cache_t = std::conditional_t<Cache, detail::value_proxy<reference>,
+                                     detail::ignore_proxy>;
+  using predicate_t = std::function<bool(reference)>;
 
 public:
   filter_iterator() = default;
@@ -47,9 +49,12 @@ public:
   }
 
 public:
-  bool should_advance() { return !base_.at_end() && !pred_(dereference()); }
+  bool should_advance() {
+    return !base_.at_end() && !pred_(cache_ = dereference());
+  }
 
   end_aware_iterator<Iter> base_;
+  cache_t cache_;
   predicate_t pred_;
 };
 
@@ -61,4 +66,7 @@ template <typename P, typename It>
 filter_iterator(P, It, It) -> filter_iterator<It>;
 }
 
-MAKE_ITERATOR_FACADE_TYPEDEFS_T(::iterator::filter_iterator);
+template <typename It, bool B>
+struct std::iterator_traits<::iterator::filter_iterator<It, B>>
+    : std::iterator_traits<
+          ::iterator::facade<::iterator::filter_iterator<It, B>>> {};

+ 1 - 1
include/iterator/iterator_fwd.hpp

@@ -18,7 +18,7 @@ template <typename, typename = unbounded> class rimpl;
 
 namespace iterator {
 template <typename> class end_aware_iterator;
-template <typename> class filter_iterator;
+template <typename, bool = false> class filter_iterator;
 template <typename> class joining_iterator;
 template <typename> class unkeyed_iterator;
 template <typename...> class zip_iterator;