Quellcode durchsuchen

Remove functions in unkeyed_iterator that are realistically never going to be used except in the case of mis-application.
Add test coverage for all functions in unkeyed_iterator

Sam Jaffe vor 5 Jahren
Ursprung
Commit
7b7e6648e6
2 geänderte Dateien mit 74 neuen und 26 gelöschten Zeilen
  1. 15 21
      include/iterator/unkeyed_iterator.hpp
  2. 59 5
      test/unkeyed_iterator_test.cxx

+ 15 - 21
include/iterator/unkeyed_iterator.hpp

@@ -10,6 +10,21 @@
 #include <iterator>
 
 namespace iterator {
+  /**
+   * At first glance, this class seems like it acts as an iterator that would be
+   * used in the C++ equivalent of Java's Map::values() function. However,
+   * notices that we do not assume that the input iterator is a map iterator.
+   * The useful feature of this iterator - and the source of its name - is its
+   * ability to be composed with recursive_iterator. This means that you can
+   * have something crazy like a four-level map and then do:
+   * \code
+   * std::map<int, std::map<std::string, std::map<int, BigType>>> object;
+   * auto const rit = make_recursive_iterator(object);
+   * for (unkeyed_iterator<decltype(rit)> it = rit, end = {}; it != end; ++it) {
+   *   // Process only BigType, discarding all of the keys that we need to walk
+   * }
+   * \endcode
+   */
   template <typename Iterator> class unkeyed_iterator {
   private:
     using impl_value_type = typename std::iterator_traits<Iterator>::value_type;
@@ -53,33 +68,12 @@ namespace iterator {
       return tmp;
     }
 
-    unkeyed_iterator operator+(difference_type n) const {
-      return unkeyed_iterator{*this} += n;
-    }
-    unkeyed_iterator & operator+=(difference_type n) {
-      base += n;
-      return *this;
-    }
-    unkeyed_iterator operator-(difference_type n) const {
-      return unkeyed_iterator{*this} -= n;
-    }
-    unkeyed_iterator & operator-=(difference_type n) {
-      base -= n;
-      return *this;
-    }
-
     bool operator==(unkeyed_iterator const & other) const {
       return base == other.base;
     }
     bool operator!=(unkeyed_iterator const & other) const {
       return base != other.base;
     }
-    bool operator<(unkeyed_iterator const & other) const {
-      return base < other.base;
-    }
-    bool operator<=(unkeyed_iterator const & other) const {
-      return !(other < *this);
-    }
 
   private:
     Iterator base;

+ 59 - 5
test/unkeyed_iterator_test.cxx

@@ -5,19 +5,73 @@
 
 #include <gmock/gmock.h>
 
+#include "iterator/end_aware_iterator.hpp"
+
+using value_iterator = iterator::unkeyed_iterator<std::map<int, int>::iterator>;
+
 TEST(UnkeyedIteratorTest, IteratorOnlyReturnsValues) {
   std::map<int, int> map{{1, 2}, {2, 3}};
   std::vector<int> const expected{2, 3};
-  iterator::unkeyed_iterator<std::map<int, int>::iterator>{map.begin()};
-  std::vector<int> const result{
-      iterator::unkeyed_iterator<std::map<int, int>::iterator>{map.begin()},
-      iterator::unkeyed_iterator<std::map<int, int>::iterator>{map.end()}};
+  std::vector<int> const result{value_iterator{map.begin()},
+                                value_iterator{map.end()}};
   EXPECT_THAT(result, expected);
 }
 
 TEST(UnkeyedIteratorTest, CanModifyIteratedCollectionValues) {
   std::map<int, int> map{{1, 2}, {2, 3}};
-  iterator::unkeyed_iterator<std::map<int, int>::iterator> uit{map.begin()};
+  value_iterator uit{map.begin()};
   *uit = 4;
   EXPECT_THAT(map[1], 4);
 }
+
+TEST(UnkeyedIteratorTest, PreIncrementAdvancesIterator) {
+  std::map<int, int> map{{1, 2}, {2, 3}};
+  value_iterator it(map.begin());
+  EXPECT_THAT(*it, 2);
+  EXPECT_THAT(*++it, 3);
+  EXPECT_THAT(*it, 3);
+}
+
+TEST(UnkeyedIteratorTest, PostIncrementReturnsCopyOfPrev) {
+  std::map<int, int> map{{1, 2}, {2, 3}};
+  value_iterator it(map.begin());
+  EXPECT_THAT(*it, 2);
+  EXPECT_THAT(*it++, 2);
+  EXPECT_THAT(*it, 3);
+}
+
+TEST(UnkeyedIteratorTest, PreDecrementAdvancesIterator) {
+  std::map<int, int> map{{1, 2}, {2, 3}};
+  value_iterator it(++map.begin());
+  EXPECT_THAT(*it, 3);
+  EXPECT_THAT(*--it, 2);
+  EXPECT_THAT(*it, 2);
+}
+
+TEST(UnkeyedIteratorTest, PostDecrementReturnsCopyOfPrev) {
+  std::map<int, int> map{{1, 2}, {2, 3}};
+  value_iterator it(++map.begin());
+  EXPECT_THAT(*it, 3);
+  EXPECT_THAT(*it--, 3);
+  EXPECT_THAT(*it, 2);
+}
+
+TEST(UnkeyedIteratorTest, EqualityIsPassthrough) {
+  std::map<int, int> map{{1, 2}, {2, 3}};
+  EXPECT_THAT(++value_iterator(map.begin()), value_iterator(++map.begin()));
+  EXPECT_THAT(value_iterator(map.begin()),
+              testing::Ne(value_iterator(++map.begin())));
+}
+
+TEST(UnkeyedIteratorTest, IffBaseIteratorEmptyIsEndThenEmptyIsEnd) {
+  std::map<int, int> map{{1, 2}, {2, 3}};
+  EXPECT_THAT(value_iterator(), testing::Ne(value_iterator(map.end())));
+  iterator::end_aware_iterator<decltype(map.end())> end(map.end());
+  EXPECT_THAT(iterator::unkeyed_iterator<decltype(end)>(),
+              iterator::unkeyed_iterator<decltype(end)>(end));
+}
+
+TEST(UnkeyedIteratorTest, CanPointToObject) {
+  std::map<int, int> map{{1, 2}, {2, 3}};
+  EXPECT_THAT(value_iterator(map.begin()).operator->(), &(map.begin()->second));
+}