فهرست منبع

Adding filter_iterator, which allows the consumer to discard elements of a collection based on a provided predicate.

Samuel Jaffe 8 سال پیش
والد
کامیت
ff8bdac761
3فایلهای تغییر یافته به همراه115 افزوده شده و 1 حذف شده
  1. 65 0
      filter_iterator.hpp
  2. 44 0
      filter_iterator.t.h
  3. 6 1
      iterator.xcodeproj/project.pbxproj

+ 65 - 0
filter_iterator.hpp

@@ -0,0 +1,65 @@
+//
+//  filter_iterator.hpp
+//  iterator
+//
+//  Created by Sam Jaffe on 6/17/17.
+//
+
+#pragma once
+
+#include "end_aware_iterator.hpp"
+
+namespace iterator {
+  template <typename Iter>
+  class filter_iterator : public end_aware_iterator<Iter> {
+  private:
+    using super = end_aware_iterator<Iter>;
+  public:
+    using value_type = typename super::value_type;
+    using reference = typename super::reference;
+    using pointer = typename super::pointer;
+    using difference_type = typename super::difference_type;
+    using iterator_category = typename super::iterator_category;
+  public:
+    filter_iterator() = default;
+    template <typename... Args>
+    filter_iterator(std::function<bool(value_type const &)> && p, Args &&... super_args)
+    : super(std::forward<Args>(super_args)...)
+    , pred(std::move(p)) {
+      if (should_advance()) { advance(); }
+    }
+    
+    filter_iterator & operator++() {
+      advance();
+      return *this;
+    }
+    
+    filter_iterator operator++(int) {
+      filter_iterator tmp{*this};
+      operator++();
+      return tmp;
+    }
+  private:
+    bool should_advance() {
+      return !super::done() && !pred(super::operator*());
+    }
+    void advance() {
+      do { super::operator++(); } while (should_advance());
+    }
+    std::function<bool(value_type const &)> pred;
+  };
+}
+
+template <typename Pred, typename Iter>
+iterator::filter_iterator<Iter> make_filter_iterator(Pred && p, Iter it, Iter end) { return {p, it, end}; }
+
+template <typename Pred, typename C>
+auto make_filter_iterator(Pred && p, C & collect) -> iterator::filter_iterator<decltype(std::begin(collect))> {
+  return { p, std::begin(collect), std::end(collect) };
+}
+
+template <typename Pred, typename C>
+auto make_filter_iterator(Pred && p, C const & collect) -> iterator::filter_iterator<decltype(std::begin(collect))> {
+  return { p, std::begin(collect), std::end(collect) };
+}
+

+ 44 - 0
filter_iterator.t.h

@@ -0,0 +1,44 @@
+//
+//  filter_iterator.t.h
+//  iterator
+//
+//  Created by Sam Jaffe on 6/17/17.
+//
+
+#pragma once
+
+#include <cxxtest/TestSuite.h>
+
+#include "filter_iterator.hpp"
+
+class filter_iterator_TestSuite : public CxxTest::TestSuite {
+public:
+  void test_returns_subset() {
+    int data[] = { 1, 2, 3, 4, 5 };
+    auto pred = [](int i) { return i%2 == 0; };
+    auto it = make_filter_iterator(pred, data);
+    decltype(it) end = {};
+    TS_ASSERT_EQUALS(std::distance(it, end), 2);
+    TS_ASSERT_EQUALS(*it++, 2);
+    TS_ASSERT_EQUALS(*it++, 4);
+  }
+  
+  void test_no_matches_marks_end() {
+    int data[] = { 1, 3, 5 };
+    auto pred = [](int i) { return i%2 == 0; };
+    auto it = make_filter_iterator(pred, data);
+    decltype(it) end = {};
+    TS_ASSERT_EQUALS(it, end);
+  }
+  
+  void test_cannot_advance_past_end() {
+    int data[] = { 1, 2, 3, 4, 5 };
+    auto pred = [](int i) { return i%2 == 0; };
+    auto it = make_filter_iterator(pred, data);
+    decltype(it) end = {};
+    ++++it;
+    TS_ASSERT_EQUALS(it, end);
+    ++it;
+    TS_ASSERT_EQUALS(it, end);
+  }
+};

+ 6 - 1
iterator.xcodeproj/project.pbxproj

@@ -31,6 +31,8 @@
 		CD21AE2C1E4A3EC100536178 /* join_iterator.hpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = join_iterator.hpp; sourceTree = "<group>"; };
 		CD21AE2E1E4A3F8E00536178 /* end_aware_iterator.hpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = end_aware_iterator.hpp; sourceTree = "<group>"; };
 		CD21AE2F1E4A428D00536178 /* end_aware_iterator.t.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = end_aware_iterator.t.h; sourceTree = "<group>"; };
+		CD46DF4B1EF5A6600092D121 /* filter_iterator.hpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = filter_iterator.hpp; sourceTree = "<group>"; };
+		CD46DF4C1EF5A69F0092D121 /* filter_iterator.t.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = filter_iterator.t.h; sourceTree = "<group>"; };
 		CD595EDF1E5BA27300FC25BB /* unkeyed_iterator.hpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = unkeyed_iterator.hpp; sourceTree = "<group>"; };
 		CD595EE01E5BA3D300FC25BB /* unkeyed_iterator.t.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = unkeyed_iterator.t.h; sourceTree = "<group>"; };
 		CD679D721E5D127600F9F843 /* recursive_iterator_meta.hpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = recursive_iterator_meta.hpp; sourceTree = "<group>"; };
@@ -81,6 +83,7 @@
 				CD679D731E5D19B900F9F843 /* recursive_iterator_accessors.t.h */,
 				CD595EE01E5BA3D300FC25BB /* unkeyed_iterator.t.h */,
 				CD13DDDD1E6CAB1500554B52 /* indexed_iterator.t.h */,
+				CD46DF4C1EF5A69F0092D121 /* filter_iterator.t.h */,
 				CD21AE291E4A3EB000536178 /* iterator_tc.cpp */,
 			);
 			name = test;
@@ -96,6 +99,7 @@
 				CD679D721E5D127600F9F843 /* recursive_iterator_meta.hpp */,
 				CD595EDF1E5BA27300FC25BB /* unkeyed_iterator.hpp */,
 				CD13DDDC1E6CAB0A00554B52 /* indexed_iterator.hpp */,
+				CD46DF4B1EF5A6600092D121 /* filter_iterator.hpp */,
 			);
 			name = src;
 			sourceTree = "<group>";
@@ -167,13 +171,14 @@
 				"$(SRCROOT)/recursive_iterator_accessors.t.h",
 				"$(SRCROOT)/unkeyed_iterator.t.h",
 				"$(SRCROOT)/indexed_iterator.t.h",
+				"$(SRCROOT)/filter_iterator.t.h",
 			);
 			outputPaths = (
 				"$(SRCROOT)/iterator_tc.cpp",
 			);
 			runOnlyForDeploymentPostprocessing = 0;
 			shellPath = /bin/sh;
-			shellScript = "cxxtestgen --error-printer -o iterator_tc.cpp end_aware_iterator.t.h join_iterator.t.h recursive_iterator_one_dimension.t.h recursive_iterator_nested_map.t.h recursive_iterator_mixed_container.t.h recursive_iterator_accessors.t.h unkeyed_iterator.t.h indexed_iterator.t.h";
+			shellScript = "cxxtestgen --error-printer -o iterator_tc.cpp end_aware_iterator.t.h join_iterator.t.h recursive_iterator_one_dimension.t.h recursive_iterator_nested_map.t.h recursive_iterator_mixed_container.t.h recursive_iterator_accessors.t.h unkeyed_iterator.t.h indexed_iterator.t.h filter_iterator.t.h";
 		};
 /* End PBXShellScriptBuildPhase section */