[ADT] Add filter_iterator for filtering elements

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

llvm-svn: 278569
diff --git a/llvm/unittests/Support/IteratorTest.cpp b/llvm/unittests/Support/IteratorTest.cpp
index 853d16c..63dfa2a 100644
--- a/llvm/unittests/Support/IteratorTest.cpp
+++ b/llvm/unittests/Support/IteratorTest.cpp
@@ -116,4 +116,73 @@
   EXPECT_EQ(End, I);
 }
 
+TEST(FilterIteratorTest, Lambda) {
+  auto IsOdd = [](int N) { return N % 2 == 1; };
+  int A[] = {0, 1, 2, 3, 4, 5, 6};
+  auto Range = make_filter_range(A, IsOdd);
+  SmallVector<int, 3> Actual(Range.begin(), Range.end());
+  EXPECT_EQ((SmallVector<int, 3>{1, 3, 5}), Actual);
+}
+
+TEST(FilterIteratorTest, CallableObject) {
+  int Counter = 0;
+  struct Callable {
+    int &Counter;
+
+    Callable(int &Counter) : Counter(Counter) {}
+
+    bool operator()(int N) {
+      Counter++;
+      return N % 2 == 1;
+    }
+  };
+  Callable IsOdd(Counter);
+  int A[] = {0, 1, 2, 3, 4, 5, 6};
+  auto Range = make_filter_range(A, IsOdd);
+  EXPECT_EQ(2, Counter);
+  SmallVector<int, 3> Actual(Range.begin(), Range.end());
+  EXPECT_GE(Counter, 7);
+  EXPECT_EQ((SmallVector<int, 3>{1, 3, 5}), Actual);
+}
+
+TEST(FilterIteratorTest, FunctionPointer) {
+  bool (*IsOdd)(int) = [](int N) { return N % 2 == 1; };
+  int A[] = {0, 1, 2, 3, 4, 5, 6};
+  auto Range = make_filter_range(A, IsOdd);
+  SmallVector<int, 3> Actual(Range.begin(), Range.end());
+  EXPECT_EQ((SmallVector<int, 3>{1, 3, 5}), Actual);
+}
+
+TEST(FilterIteratorTest, Composition) {
+  auto IsOdd = [](int N) { return N % 2 == 1; };
+  std::unique_ptr<int> A[] = {make_unique<int>(0), make_unique<int>(1),
+                              make_unique<int>(2), make_unique<int>(3),
+                              make_unique<int>(4), make_unique<int>(5),
+                              make_unique<int>(6)};
+  using PointeeIterator = pointee_iterator<std::unique_ptr<int> *>;
+  auto Range = make_filter_range(
+      make_range(PointeeIterator(std::begin(A)), PointeeIterator(std::end(A))),
+      IsOdd);
+  SmallVector<int, 3> Actual(Range.begin(), Range.end());
+  EXPECT_EQ((SmallVector<int, 3>{1, 3, 5}), Actual);
+}
+
+TEST(FilterIteratorTest, InputIterator) {
+  struct InputIterator
+      : iterator_adaptor_base<InputIterator, int *, std::input_iterator_tag> {
+    using BaseT =
+        iterator_adaptor_base<InputIterator, int *, std::input_iterator_tag>;
+
+    InputIterator(int *It) : BaseT(It) {}
+  };
+
+  auto IsOdd = [](int N) { return N % 2 == 1; };
+  int A[] = {0, 1, 2, 3, 4, 5, 6};
+  auto Range = make_filter_range(
+      make_range(InputIterator(std::begin(A)), InputIterator(std::end(A))),
+      IsOdd);
+  SmallVector<int, 3> Actual(Range.begin(), Range.end());
+  EXPECT_EQ((SmallVector<int, 3>{1, 3, 5}), Actual);
+}
+
 } // anonymous namespace