浏览代码

Adding several test cases.
- Reducing redundant code with dispatch-constructors
- Creating factory methods for type deduction in recursive and end_aware iterators
- Fixing bugs in three+layer recursion where data didn't propagate (assign())
- Fixing bug that would cause value_type of tuple/pair to be unrolled into the recursive tuple incorrectly (next_layer_type)

Samuel Jaffe 8 年之前
父节点
当前提交
d3eedc2fc2

+ 57 - 45
end_aware_iterator.hpp

@@ -12,51 +12,63 @@
 #include <iterator>
 
 namespace iterator {
-template <typename Iterator>
-class end_aware_iterator {
-public:
-  using iter_type = Iterator;
-  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:
-  end_aware_iterator() = default;
-  end_aware_iterator(iter_type it, iter_type end) : curr_(it), end_(end) {}
-  
-  template <typename I>
-  end_aware_iterator( end_aware_iterator<I> const & other )
-  : curr_(other.current()), end_(other.end()) {
+  template <typename Iterator>
+  class end_aware_iterator {
+  public:
+    using iter_type = Iterator;
+    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:
+    end_aware_iterator() = default;
+    end_aware_iterator(iter_type it, iter_type end) : curr_(it), end_(end) {}
+    end_aware_iterator(iter_type end) : curr_(end), end_(end) {}
     
-  }
-  
-  end_aware_iterator & operator++() {
-    if ( !done() ) { ++curr_; }
-    return *this;
-  }
-  
-  end_aware_iterator operator++(int) {
-    end_aware_iterator tmp{*this};
-    operator++();
-    return tmp;
-  }
+    template <typename I>
+    end_aware_iterator( end_aware_iterator<I> const & other )
+    : curr_(other.current()), end_(other.end()) {
+      
+    }
+    
+    end_aware_iterator & operator++() {
+      if ( !done() ) { ++curr_; }
+      return *this;
+    }
+    
+    end_aware_iterator operator++(int) {
+      end_aware_iterator tmp{*this};
+      operator++();
+      return tmp;
+    }
+    
+    reference operator*() { return *curr_; }
+    pointer operator->() { return std::addressof(*curr_); }
+    
+    bool done() const { return curr_ == end_; }
+    bool operator==(end_aware_iterator const & other) const {
+      return (done() && other.done()) || (curr_ == other.curr_ && end_ == other.end_);
+    }
+    
+    bool operator!=(end_aware_iterator const & other) {
+      return !(operator==(other));
+    }
+    
+    iter_type current() const { return curr_; }
+    iter_type end() const { return end_; }
+  private:
+    iter_type curr_, end_;
+  };
+}
 
-  reference operator*() { return *curr_; }
-  pointer operator->() { return std::addressof(*curr_); }
-  
-  bool done() const { return curr_ == end_; }
-  bool operator==(end_aware_iterator const & other) const {
-    return curr_ == other.curr_ && end_ == other.end_;
-  }
-  
-  bool operator!=(end_aware_iterator const & other) {
-    return !(operator==(other));
-  }
-  
-  iter_type current() const { return curr_; }
-  iter_type end() const { return end_; }
-private:
-  iter_type curr_, end_;
-};
+template <typename C>
+auto make_end_aware_iterator(C & collect) -> iterator::end_aware_iterator<decltype(std::begin(collect))> {
+  return { std::begin(collect), std::end(collect) };
 }
+
+template <typename C>
+auto make_end_aware_iterator(C const & collect) -> iterator::end_aware_iterator<decltype(std::begin(collect))> {
+  return { std::begin(collect), std::end(collect) };
+}
+

+ 13 - 3
iterator.xcodeproj/project.pbxproj

@@ -30,8 +30,10 @@
 		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>"; };
 		CD7172E91E57C6580048DFFF /* recursive_iterator.hpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = recursive_iterator.hpp; sourceTree = "<group>"; };
-		CD7172EA1E57C91D0048DFFF /* recursive_iterator.t.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = recursive_iterator.t.h; sourceTree = "<group>"; };
+		CD7172EA1E57C91D0048DFFF /* recursive_iterator_one_dimension.t.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = recursive_iterator_one_dimension.t.h; sourceTree = "<group>"; };
 		CD7172EC1E5897B80048DFFF /* iterator_fwd.hpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = iterator_fwd.hpp; sourceTree = "<group>"; };
+		CD7172ED1E58BC930048DFFF /* recursive_iterator_nested_map.t.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = recursive_iterator_nested_map.t.h; sourceTree = "<group>"; };
+		CD7172EE1E58C9930048DFFF /* recursive_iterator_mixed_container.t.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = recursive_iterator_mixed_container.t.h; sourceTree = "<group>"; };
 /* End PBXFileReference section */
 
 /* Begin PBXFrameworksBuildPhase section */
@@ -67,7 +69,9 @@
 			children = (
 				CD21AE2F1E4A428D00536178 /* end_aware_iterator.t.h */,
 				CD21AE2A1E4A3EB000536178 /* join_iterator.t.h */,
-				CD7172EA1E57C91D0048DFFF /* recursive_iterator.t.h */,
+				CD7172EA1E57C91D0048DFFF /* recursive_iterator_one_dimension.t.h */,
+				CD7172ED1E58BC930048DFFF /* recursive_iterator_nested_map.t.h */,
+				CD7172EE1E58C9930048DFFF /* recursive_iterator_mixed_container.t.h */,
 				CD21AE291E4A3EB000536178 /* iterator_tc.cpp */,
 			);
 			name = test;
@@ -143,12 +147,18 @@
 			files = (
 			);
 			inputPaths = (
+				"$(SRCROOT)/end_aware_iterator.t.h",
+				"$(SRCROOT)/join_iterator.t.h",
+				"$(SRCROOT)/recursive_iterator_one_dimension.t.h",
+				"$(SRCROOT)/recursive_iterator_nested_map.t.h",
+				"$(SRCROOT)/recursive_iterator_mixed_container.t.h",
 			);
 			outputPaths = (
+				"$(SRCROOT)/iterator_tc.cpp",
 			);
 			runOnlyForDeploymentPostprocessing = 0;
 			shellPath = /bin/sh;
-			shellScript = "cxxtestgen --error-printer -o iterator_tc.cpp join_iterator.t.h end_aware_iterator.t.h recursive_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";
 		};
 /* End PBXShellScriptBuildPhase section */
 

+ 62 - 70
join_iterator.hpp

@@ -13,79 +13,71 @@
 #include <iterator>
 
 namespace iterator {
-template <typename MetaIterator>
-class joining_iterator {
-public:
-  using join_iter = MetaIterator;
-  using joinable_type = typename join_iter::value_type;
-  using iter_type = detail::value_iterator<MetaIterator>;
- 
-  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( )
-  : joiner_({}, {}), iterator_({}, {}) {
+  template <typename MetaIterator>
+  class joining_iterator {
+  public:
+    using join_iter = MetaIterator;
+    using joinable_type = typename join_iter::value_type;
+    using iter_type = detail::value_iterator<MetaIterator>;
     
-  }
-  
-  template <typename I>
-  joining_iterator( joining_iterator<I> const & other )
-  : joiner_(other.join_iterator()), iterator_(other.element_iterator()) {
+    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;
     
-  }
-  
-  joining_iterator( join_iter start, join_iter end )
-  : joiner_(start, end), iterator_({}, {}) {
-    update_iterator();
-  }
-
-  joining_iterator( join_iter start, join_iter end, iter_type lstart, iter_type lend, bool update = false )
-  : joiner_(start, end), iterator_(lstart, lend) {
-    if ( update ) { update_iterator(); }
-  }
-
-  joining_iterator & operator++() {
-    if ( (++iterator_).done() ) {
-      ++joiner_;
-      update_iterator();
+    template <typename I>
+    joining_iterator( joining_iterator<I> const & other )
+    : joiner_(other.join_iterator()), iterator_(other.element_iterator()) {
+      
+    }
+    
+    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) {
+      if ( update ) { update_iterator(); }
+    }
+    
+    joining_iterator & operator++() {
+      if ( (++iterator_).done() ) {
+        ++joiner_;
+        update_iterator();
+      }
+      return *this;
+    }
+    
+    joining_iterator operator++(int) {
+      joining_iterator tmp{*this};
+      operator++();
+      return tmp;
     }
-    return *this;
-  }
-  
-  joining_iterator operator++(int) {
-    joining_iterator tmp{*this};
-    operator++();
-    return tmp;
-  }
-  
-  reference operator*() { return iterator_.operator*(); }
-  pointer operator->() { return iterator_.operator->(); }
-  
-  bool operator==(joining_iterator const & other) const {
-    return joiner_ == other.joiner_ && ((joiner_.done() && other.joiner_.done()) ||
-                                        iterator_ == other.iterator_);
-  }
-  
-  bool operator!=(joining_iterator const & other) {
-    return !(operator==(other));
-  }
-  
-  end_aware_iterator<join_iter> join_iterator() const { return joiner_; }
-  end_aware_iterator<iter_type> element_iterator() const { return iterator_; }
-private:
-  void update_iterator() {
-    while ( !joiner_.done() && std::begin(*joiner_) == std::end(*joiner_) ) {
-      ++joiner_;
+    
+    reference operator*() { return iterator_.operator*(); }
+    pointer operator->() { return iterator_.operator->(); }
+    
+    bool operator==(joining_iterator const & other) const {
+      return joiner_ == other.joiner_ && iterator_ == other.iterator_;
     }
-    if ( !joiner_.done() ) {
-      iterator_ = { std::begin(*joiner_), std::end(*joiner_) };
+    
+    bool operator!=(joining_iterator const & other) {
+      return !(operator==(other));
     }
-  }
-  
-  end_aware_iterator<join_iter> joiner_;
-  end_aware_iterator<iter_type> iterator_;
-};
+    
+    end_aware_iterator<join_iter> join_iterator() const { return joiner_; }
+    end_aware_iterator<iter_type> element_iterator() const { return iterator_; }
+  private:
+    void update_iterator() {
+      while ( !joiner_.done() && std::begin(*joiner_) == std::end(*joiner_) ) {
+        ++joiner_;
+      }
+      if ( !joiner_.done() ) {
+        iterator_ = { std::begin(*joiner_), std::end(*joiner_) };
+      }
+    }
+    
+    end_aware_iterator<join_iter> joiner_;
+    end_aware_iterator<iter_type> iterator_;
+  };
 }

+ 9 - 3
join_iterator.t.h

@@ -21,18 +21,24 @@ public:
 public:
   void test_points_to_beginning() {
     meta_vec_t mv{{1,2,3},{4,5,6}};
-    TS_ASSERT_EQUALS(*jn_iter(mv.begin(), mv.end()), mv[0][0]);
+    TS_ASSERT_EQUALS(*jn_iter(make_end_aware_iterator(mv)), mv[0][0]);
+  }
+  
+  void test_empty_constructor_is_end() {
+    meta_vec_t mv{{1,2,3},{4,5,6}};
+    jn_iter it( { mv.end(), mv.end() }, { mv.back().end(), mv.back().end() } );
+    TS_ASSERT_EQUALS(it, jn_iter());
   }
   
   void test_steps_to_next_list() {
     meta_vec_t mv{{1,2,3},{4,5,6}};
-    jn_iter it(mv.begin(), mv.end(), mv.front().end(), mv.front().end());
+    jn_iter it(make_end_aware_iterator(mv), { mv[0].end(), mv[0].end() });
     TS_ASSERT_EQUALS(*++it, mv[1][0]);
   }
   
   void test_cannot_go_past_end() {
     meta_vec_t mv{{1,2,3},{4,5,6}};
-    jn_iter it(mv.end(), mv.end(), mv.back().end(), mv.back().end());
+    jn_iter it( { mv.end(), mv.end() }, { mv.back().end(), mv.back().end() });
     jn_iter const cp = it;
     ++it;
     TS_ASSERT_EQUALS(it, cp);

+ 265 - 220
recursive_iterator.hpp

@@ -10,253 +10,298 @@
 #include "iterator_fwd.hpp"
 
 namespace iterator {
-namespace detail {  
-//  template <typename Iterator>
-//  using recursive_iterator_base = end_aware_iterator< Iterator >;
-  
-  template <typename Iterator, typename = void>
-  class recursive_iterator_base : public end_aware_iterator<Iterator> {
-  private:
-    using super = end_aware_iterator<Iterator>;
-  public:
-    using super::super;
-  };
-
-  template <typename Iterator>
-  class recursive_iterator_base<Iterator, typename std::enable_if<std::is_const<typename end_aware_iterator<Iterator>::value_type::first_type>::value>::type> : public end_aware_iterator<Iterator> {
-  private:
-    using super = end_aware_iterator<Iterator>;
-    using first_type = typename super::value_type::first_type;
-    using second_type = typename super::value_type::second_type;
-  public:
-    using value_type = std::tuple<first_type, second_type>;
-    using reference = std::tuple<first_type &, second_type &>;
-  public:
-    using super::super;
-  };
-
-  template <typename Iterator, typename = void>
-  class recursive_iterator_terminal : public recursive_iterator_base< Iterator > {
-  private:
-    using layer = recursive_iterator_base< Iterator >;
-  public:
-    recursive_iterator_terminal() = default;
-    recursive_iterator_terminal(layer v) : layer(v) {}
+  namespace detail {
+    struct terminal_layer_tag_t;
+    struct continue_layer_tag_t;
     
-    typename layer::reference operator*() {
-      return layer::operator*();
-    }
+    template <typename Iterator, typename = void>
+    class recursive_iterator_base : public end_aware_iterator<Iterator> {
+    private:
+      using super = end_aware_iterator<Iterator>;
+    protected:
+      using recursive_category = terminal_layer_tag_t;
+    public:
+      using super::super;
+    };
     
-    typename layer::pointer operator->() {
-      return layer::operator->();
-    }
-  protected:
-    void next() {
-      layer::operator++();
-    }
-    
-    void assign(layer eat) {
-      static_cast<layer&>(*this) = eat;
-    }
-    
-    bool done() const { return layer::done(); }
-  };
-  
-  template <typename Iterator, typename RecursiveIterator_NextLayer>
-  class recursive_iterator_layer :
-  public recursive_iterator_base< Iterator >,
-  public RecursiveIterator_NextLayer {
-  private:
-    using next_layer = RecursiveIterator_NextLayer;
-    using layer = recursive_iterator_base< Iterator >;
-  public:
-    using value_type = typename next_layer::value_type;
-    using reference = typename next_layer::reference;
-    using pointer = typename next_layer::pointer;
-    using difference_type = typename next_layer::difference_type;
-    using iterator_category = typename next_layer::iterator_category;
-  public:
-    recursive_iterator_layer() = default;
-    recursive_iterator_layer(layer v) : layer(v), next_layer() {
-      if ( !v.done() ) {
-        next_layer::assign({ std::begin(*v), std::end(*v) });
+    template <typename Iterator>
+    class recursive_iterator_base<Iterator, typename std::enable_if<std::is_const<typename end_aware_iterator<Iterator>::value_type::first_type>::value>::type> : public end_aware_iterator<Iterator> {
+    private:
+      using super = end_aware_iterator<Iterator>;
+      using first_type = decltype((std::declval<Iterator>()->first));
+      using second_type = decltype((std::declval<Iterator>()->second));
+    protected:
+      using recursive_category = continue_layer_tag_t;
+    public:
+      using value_type = std::tuple<first_type, second_type>;
+      using reference = std::tuple<first_type &, second_type &>;
+    public:
+      reference operator*() {
+        auto & pair = super::operator*();
+        return std::tie(pair.first, pair.second);
       }
-    }
-    
-    reference operator*() {
-      return next_layer::operator*();
-    }
+      
+      using super::super;
+    };
     
-    pointer operator->() {
-      return next_layer::operator->();
-    }
+    template <typename Iterator, typename = void>
+    class recursive_iterator_terminal : public recursive_iterator_base< Iterator > {
+    private:
+      using layer = recursive_iterator_base< Iterator >;
+    public:
+      recursive_iterator_terminal() = default;
+      recursive_iterator_terminal(layer v) : layer(v) {}
+      
+      typename layer::reference operator*() {
+        return layer::operator*();
+      }
+      
+      typename layer::pointer operator->() {
+        return layer::operator->();
+      }
+    protected:
+      void next() {
+        layer::operator++();
+      }
+      
+      void assign(layer eat) {
+        static_cast<layer&>(*this) = eat;
+      }
+      
+      bool done() const { return layer::done(); }
+    };
     
-    bool operator==(recursive_iterator_layer const & other) const {
-      return layer::operator==(other) && next_layer::operator==(other);
-    }
-  protected:
-    void next() {
-      layer & self = static_cast<layer&>(*this);
-      next_layer::next();
-      while ( next_layer::done() && !(++self).done() ) {
-        next_layer::assign({ std::begin(*self), std::end(*self) });
+    template <typename Iterator, typename RecursiveIterator_NextLayer>
+    class recursive_iterator_layer :
+    public recursive_iterator_base< Iterator >,
+    public RecursiveIterator_NextLayer {
+    private:
+      using next_layer = RecursiveIterator_NextLayer;
+      using layer = recursive_iterator_base< Iterator >;
+    protected:
+      using recursive_category = continue_layer_tag_t;
+    public:
+      using value_type = typename next_layer::value_type;
+      using reference = typename next_layer::reference;
+      using pointer = typename next_layer::pointer;
+      using difference_type = typename next_layer::difference_type;
+      using iterator_category = typename next_layer::iterator_category;
+    public:
+      recursive_iterator_layer() = default;
+      recursive_iterator_layer(layer v) : recursive_iterator_layer() {
+        assign(v);
       }
-    }
+      
+      reference operator*() {
+        return next_layer::operator*();
+      }
+      
+      pointer operator->() {
+        return next_layer::operator->();
+      }
+      
+      bool operator==(recursive_iterator_layer const & other) const {
+        return layer::operator==(other) && next_layer::operator==(other);
+      }
+    protected:
+      void next() {
+        layer & self = static_cast<layer&>(*this);
+        next_layer::next();
+        while ( next_layer::done() && !(++self).done() ) {
+          next_layer::assign({ std::begin(*self), std::end(*self) });
+        }
+      }
+      
+      void assign(layer v) {
+        static_cast<layer&>(*this) = v;
+        if (!v.done()) {
+          next_layer::assign({ std::begin(*v), std::end(*v) });
+        }
+      }
+      
+      bool done() const { return layer::done(); }
+    };
     
-    void assign(layer eat) {
-      static_cast<layer&>(*this) = eat;
-    }
+    template <typename V, typename Tag>
+    struct next_layer_type { using type = std::tuple<V>; };
+    template <typename V>
+    struct next_layer_type<V, continue_layer_tag_t> { using type = V; };
     
-    bool done() const { return layer::done(); }
-  };
-  
-  template <typename Iterator, typename RecursiveIterator_NextLayer>
-  class flatten_iterator_layer :
-  recursive_iterator_base< Iterator >,
-  RecursiveIterator_NextLayer {
-  private:
-    using next_layer = RecursiveIterator_NextLayer;
-    using layer = recursive_iterator_base< Iterator >;
-    using key_type = typename std::tuple_element<0, typename layer::value_type>::type;
-  public:
-    using value_type = decltype(std::tuple_cat(std::make_tuple(std::declval<key_type>()), std::declval<typename next_layer::value_type>()));
-    using reference = decltype(std::tuple_cat(std::tie(std::declval<key_type>()), std::declval<typename next_layer::reference>()));
-    using pointer = void;
-    using difference_type = typename next_layer::difference_type;
-    using iterator_category = typename next_layer::iterator_category;
-  public:
-    flatten_iterator_layer() = default;
-    flatten_iterator_layer(layer v) : layer(v), next_layer() {
-      if ( !v.done() ) {
-        next_layer::assign({ std::begin(v->second), std::end(v->second) });
+    template <typename Iterator, typename RecursiveIterator_NextLayer>
+    class flatten_iterator_layer :
+    recursive_iterator_base< Iterator >,
+    RecursiveIterator_NextLayer {
+    private:
+      using next_layer = RecursiveIterator_NextLayer;
+      using layer = recursive_iterator_base< Iterator >;
+      using key_type = typename std::tuple_element<0, typename layer::value_type>::type;
+    protected:
+      using recursive_category = continue_layer_tag_t;
+      using next_value_type = typename next_layer_type<typename next_layer::value_type, typename next_layer::recursive_category>::type;
+      using next_reference = typename next_layer_type<typename next_layer::reference, typename next_layer::recursive_category>::type;
+    public:
+      using value_type = decltype(std::tuple_cat(std::make_tuple(std::declval<key_type>()),
+                                                 std::declval<next_value_type>()));
+      using reference = decltype(std::tuple_cat(std::tie(std::declval<key_type>()),
+                                                std::declval<next_reference>()));
+      using pointer = void;
+      using difference_type = typename next_layer::difference_type;
+      using iterator_category = typename next_layer::iterator_category;
+    public:
+      flatten_iterator_layer() = default;
+      flatten_iterator_layer(layer v) : flatten_iterator_layer() {
+        assign(v);
       }
-    }
+      
+      reference operator*() {
+        return std::tuple_cat(std::forward_as_tuple(std::get<0>(layer::operator*())),
+                              next_reference(next_layer::operator*()));
+      }
+      
+      pointer operator->();
+      //    pointer operator->() {
+      //      return next_layer::operator->();
+      //    }
+      
+      bool operator==(flatten_iterator_layer const & other) const {
+        return layer::operator==(other) && next_layer::operator==(other);
+      }
+    protected:
+      void next() {
+        layer & self = static_cast<layer&>(*this);
+        next_layer::next();
+        while ( next_layer::done() && !(++self).done() ) {
+          next_layer::assign({ std::begin(self->second), std::end(self->second) });
+        }
+      }
+      
+      void assign(layer v) {
+        static_cast<layer&>(*this) = v;
+        if ( !v.done() ) {
+          next_layer::assign({ std::begin(v->second), std::end(v->second) });
+        }
+      }
+      
+      bool done() const { return layer::done(); }
+    };
     
-    reference operator*() {
-      return std::tuple_cat(std::forward_as_tuple(layer::operator*().first), next_layer::operator*());
-    }
+    template <typename Iterator, std::size_t N, std::size_t Max, typename = void>
+    class bounded_recursive_iterator_impl :
+    public recursive_iterator_terminal< Iterator > {
+    private:
+      using super = recursive_iterator_terminal< Iterator >;
+    public:
+      using super::super;
+    };
     
-    pointer operator->();
-    //    pointer operator->() {
-    //      return next_layer::operator->();
-    //    }
+    template <typename Iterator, std::size_t N, std::size_t Max>
+    class bounded_recursive_iterator_impl< Iterator, N, Max, typename std::enable_if<N < Max, typename void_t<value_iterator<Iterator>>::type>::type > :
+    public recursive_iterator_layer< Iterator , bounded_recursive_iterator_impl< value_iterator<Iterator>, N+1, Max > > {
+    private:
+      using next_layer = bounded_recursive_iterator_impl< value_iterator<Iterator>, N+1, Max >;
+      using super = recursive_iterator_layer< Iterator, next_layer >;
+    public:
+      using super::super;
+    };
     
-    bool operator==(flatten_iterator_layer const & other) const {
-      return layer::operator==(other) && next_layer::operator==(other);
-    }
-  protected:
-    void next() {
-      layer & self = static_cast<layer&>(*this);
-      next_layer::next();
-      while ( next_layer::done() && !(++self).done() ) {
-        next_layer::assign({ std::begin(self->second), std::end(self->second) });
-      }
-    }
+    template <typename Iterator, typename = void>
+    class recursive_iterator_impl : public recursive_iterator_terminal< Iterator > {
+    private:
+      using super = recursive_iterator_terminal< Iterator >;
+    public:
+      using super::super;
+    };
     
-    void assign(layer eat) {
-      static_cast<layer&>(*this) = eat;
-    }
+    template <typename Iterator>
+    class recursive_iterator_impl< Iterator, typename void_t<value_iterator<Iterator>>::type > :
+    public recursive_iterator_layer< Iterator, recursive_iterator_impl< value_iterator<Iterator> > > {
+    private:
+      using next_layer = recursive_iterator_impl< value_iterator<Iterator> >;
+      using super = recursive_iterator_layer< Iterator, next_layer >;
+    public:
+      using super::super;
+    };
     
-    bool done() const { return layer::done(); }
-  };
-  
-  template <typename Iterator, std::size_t N, std::size_t Max, typename = void>
-  class bounded_recursive_iterator_impl :
-  public recursive_iterator_terminal< Iterator > {
-  private:
-    using super = recursive_iterator_terminal< Iterator >;
-  public:
-    using super::super;
-  };
+    template <typename Iterator, std::size_t N, std::size_t Max>
+    class bounded_recursive_iterator_impl< Iterator, N, Max, typename std::enable_if<N < Max, typename void_t<mapped_iterator<Iterator>>::type>::type > :
+    public flatten_iterator_layer< Iterator , bounded_recursive_iterator_impl< mapped_iterator<Iterator>, N+1, Max > > {
+    private:
+      using next_layer = bounded_recursive_iterator_impl< mapped_iterator<Iterator>, N+1, Max >;
+      using super = flatten_iterator_layer< Iterator, next_layer >;
+    public:
+      using super::super;
+    };
     
-  template <typename Iterator, std::size_t N, std::size_t Max>
-  class bounded_recursive_iterator_impl< Iterator, N, Max, typename std::enable_if<N < Max, typename void_t<value_iterator<Iterator>>::type>::type > :
-  public recursive_iterator_layer< Iterator , bounded_recursive_iterator_impl< value_iterator<Iterator>, N+1, Max > > {
-  private:
-    using next_layer = bounded_recursive_iterator_impl< value_iterator<Iterator>, N+1, Max >;
-    using super = recursive_iterator_layer< Iterator, next_layer >;
-  public:
-    using super::super;
-  };
-  
-  template <typename Iterator, typename = void>
-  class recursive_iterator_impl : public recursive_iterator_terminal< Iterator > {
-  private:
-    using super = recursive_iterator_terminal< Iterator >;
-  public:
-    using super::super;
-  };
+    template <typename Iterator>
+    class recursive_iterator_impl< Iterator, typename void_t<mapped_iterator<Iterator>>::type > :
+    public flatten_iterator_layer< Iterator, recursive_iterator_impl< mapped_iterator<Iterator> > > {
+    private:
+      using next_layer = recursive_iterator_impl< mapped_iterator<Iterator> >;
+      using super = flatten_iterator_layer< Iterator, next_layer >;
+    public:
+      using super::super;
+    };
+  }
   
   template <typename Iterator>
-  class recursive_iterator_impl< Iterator, typename void_t<value_iterator<Iterator>>::type > :
-  public recursive_iterator_layer< Iterator, recursive_iterator_impl< value_iterator<Iterator> > > {
-  private:
-    using next_layer = recursive_iterator_impl< value_iterator<Iterator> >;
-    using super = recursive_iterator_layer< Iterator, next_layer >;
-  public:
-    using super::super;
-  };
-  
-  template <typename Iterator, std::size_t N, std::size_t Max>
-  class bounded_recursive_iterator_impl< Iterator, N, Max, typename std::enable_if<N < Max, typename void_t<mapped_iterator<Iterator>>::type>::type > :
-  public flatten_iterator_layer< Iterator , bounded_recursive_iterator_impl< mapped_iterator<Iterator>, N+1, Max > > {
+  class recursive_iterator : public detail::recursive_iterator_impl< Iterator > {
   private:
-    using next_layer = bounded_recursive_iterator_impl< mapped_iterator<Iterator>, N+1, Max >;
-    using super = flatten_iterator_layer< Iterator, next_layer >;
+    using super = detail::recursive_iterator_impl< Iterator >;
   public:
     using super::super;
+    
+    recursive_iterator & operator++() {
+      (void) super::next();
+      return *this;
+    }
+    
+    recursive_iterator operator++(int) {
+      recursive_iterator tmp{*this};
+      (void) super::next();
+      return tmp;
+    }
+    
+    bool operator!=(recursive_iterator const & other) { return !(super::operator==(other)); }
   };
   
-  template <typename Iterator>
-  class recursive_iterator_impl< Iterator, typename void_t<mapped_iterator<Iterator>>::type > :
-  public flatten_iterator_layer< Iterator, recursive_iterator_impl< mapped_iterator<Iterator> > > {
+  template <typename Iterator, std::size_t N>
+  class recursive_iterator_n : public detail::bounded_recursive_iterator_impl< Iterator, 1, N > {
   private:
-    using next_layer = recursive_iterator_impl< mapped_iterator<Iterator> >;
-    using super = flatten_iterator_layer< Iterator, next_layer >;
+    using super = detail::bounded_recursive_iterator_impl< Iterator, 1, N >;
   public:
     using super::super;
+    
+    recursive_iterator_n & operator++() {
+      (void) super::next();
+      return *this;
+    }
+    
+    recursive_iterator_n operator++(int) {
+      recursive_iterator_n tmp{*this};
+      (void) super::next();
+      return tmp;
+    }
+    
+    bool operator!=(recursive_iterator_n const & other) { return !(super::operator==(other)); }
   };
 }
 
-template <typename Iterator>
-class recursive_iterator : public detail::recursive_iterator_impl< Iterator > {
-private:
-  using super = detail::recursive_iterator_impl< Iterator >;
-public:
-  using super::super;
-  
-  recursive_iterator & operator++() {
-    (void) super::next();
-    return *this;
-  }
-  
-  recursive_iterator operator++(int) {
-    recursive_iterator tmp{*this};
-    (void) super::next();
-    return tmp;
-  }
-  
-  bool operator!=(recursive_iterator const & other) { return !(operator==(other)); }
-};
+template <typename C>
+auto make_recursive_iterator(C & collect) -> iterator::recursive_iterator<decltype(std::begin(collect))> {
+  return {{ std::begin(collect), std::end(collect) }};
+}
 
-template <typename Iterator, std::size_t N>
-class recursive_iterator_n : public detail::bounded_recursive_iterator_impl< Iterator, 1, N > {
-private:
-  using super = detail::bounded_recursive_iterator_impl< Iterator, 1, N >;
-public:
-  using super::super;
-  
-  recursive_iterator_n & operator++() {
-    (void) super::next();
-    return *this;
-  }
-  
-  recursive_iterator_n operator++(int) {
-    recursive_iterator_n tmp{*this};
-    (void) super::next();
-    return tmp;
-  }
-  
-  bool operator!=(recursive_iterator_n const & other) { return !(operator==(other)); }
-};
+template <typename C>
+auto make_recursive_iterator(C const & collect) -> iterator::recursive_iterator<decltype(std::begin(collect))> {
+  return {{ std::begin(collect), std::end(collect) }};
+}
+
+template <std::size_t Max, typename C>
+auto make_recursive_iterator(C & collect) -> iterator::recursive_iterator_n<decltype(std::begin(collect)), Max> {
+  return {{ std::begin(collect), std::end(collect) }};
+}
+
+template <std::size_t Max, typename C>
+auto make_recursive_iterator(C const & collect) -> iterator::recursive_iterator_n<decltype(std::begin(collect)), Max> {
+  return {{ std::begin(collect), std::end(collect) }};
 }

+ 71 - 0
recursive_iterator_mixed_container.t.h

@@ -0,0 +1,71 @@
+//
+//  recursive_iterator_mixed_container.t.h
+//  iterator
+//
+//  Created by Sam Jaffe on 2/18/17.
+//
+
+#pragma once
+
+#include <cxxtest/TestSuite.h>
+
+#include "recursive_iterator.hpp"
+
+class recursive_iterator_mixed_container_TestSuite : public CxxTest::TestSuite {
+public:
+  void test_map_vector_iterator_matches_size() {
+    std::map<int, std::vector<int>> const obj{{1, {1, 2}}, {2, {3, 4, 5}}};
+    std::vector<std::tuple<int, int>> const expected{{1, 1}, {1, 2}, {2, 3}, {2, 4}, {2, 5}};
+    auto rit = make_recursive_iterator(obj);
+    decltype(rit) end{ };
+    TS_ASSERT_EQUALS(std::distance(rit, end), expected.size());
+  }
+  
+  void test_map_vector_iterator_matches_data() {
+    std::map<int, std::vector<int>> const obj{{1, {1, 2}}, {2, {3, 4, 5}}};
+    std::vector<std::tuple<int, int>> const expected{{1, 1}, {1, 2}, {2, 3}, {2, 4}, {2, 5}};
+    auto rit = make_recursive_iterator(obj);
+    for (auto it = expected.begin(), end = expected.end(); it != end; ++it, ++rit) {
+      TS_ASSERT_EQUALS(*it, *rit);
+    }
+  }
+
+  void test_map_vector_iterator_can_edit_data() {
+    std::map<int, std::vector<int>> obj{{1, {1, 2}}, {2, {3, 4, 5}}};
+    auto rit = make_recursive_iterator(obj);
+    std::get<1>(*rit) = 6;
+    TS_ASSERT_EQUALS(obj[1][0], 6);
+  }
+  
+  void test_vector_map_iterator_matches_size() {
+    std::vector<std::map<int, int>> const obj{{{1, 1}, {2, 2}}, {{3, 3}, {4, 4}, {5, 5}}};
+    std::vector<std::tuple<int, int>> const expected{{1, 1}, {2, 2}, {3, 3}, {4, 4}, {5, 5}};
+    auto rit = make_recursive_iterator(obj);
+    decltype(rit) end{ };
+    TS_ASSERT_EQUALS(std::distance(rit, end), expected.size());
+  }
+  
+  void test_vector_map_iterator_matches_data() {
+    std::vector<std::map<int, int>> const obj{{{1, 1}, {2, 2}}, {{3, 3}, {4, 4}, {5, 5}}};
+    std::vector<std::tuple<int, int>> const expected{{1, 1}, {2, 2}, {3, 3}, {4, 4}, {5, 5}};
+    auto rit = make_recursive_iterator(obj);
+    for (auto it = expected.begin(), end = expected.end(); it != end; ++it, ++rit) {
+      TS_ASSERT_EQUALS(*it, *rit);
+    }
+  }
+  
+  void test_vector_map_iterator_can_edit_data() {
+    std::vector<std::map<int, int>> obj{{{1, 1}, {2, 2}}, {{3, 3}, {4, 4}, {5, 5}}};
+    auto rit = make_recursive_iterator(obj);
+    std::get<1>(*rit) = 6;
+    TS_ASSERT_EQUALS(obj[0][1], 6);
+  }
+  
+  void test_map_vector_map_iterator() {
+    std::map<int, std::vector<std::map<int, int>>> const obj{{1, {{{1, 1}, {2, 2}}}}};
+    std::vector<std::tuple<int, int, int>> const expected{{1, 1, 1}, {1, 2, 2}};
+    auto rit = make_recursive_iterator(obj);
+    decltype(rit) end{ };
+    TS_ASSERT_EQUALS(std::distance(rit, end), expected.size());
+  }
+};

+ 79 - 0
recursive_iterator_nested_map.t.h

@@ -0,0 +1,79 @@
+//
+//  recursive_iterator_nested_map.t.h
+//  iterator
+//
+//  Created by Sam Jaffe on 2/18/17.
+//
+
+#pragma once
+
+#include <cxxtest/TestSuite.h>
+
+#include "recursive_iterator.hpp"
+
+class recursive_iterator_nested_map_TestSuite : public CxxTest::TestSuite {
+public:
+  void test_map_iterator_matches_size() {
+    std::map<int, int> const map{{1, 1}, {2, 2}, {3, 3}};
+    auto rit = make_recursive_iterator(map);
+    decltype(rit) end{ };
+    TS_ASSERT_EQUALS(std::distance(rit, end), map.size());
+  }
+  
+  void test_map_iterator_matches_data() {
+    std::map<int, int> const map{{1, 1}, {2, 2}, {3, 3}};
+    auto rit = make_recursive_iterator(map);
+    for (auto it = map.begin(), end = map.end(); it != end; ++it, ++rit) {
+      TS_ASSERT_EQUALS(std::tuple_cat(*it), *rit);
+    }
+  }
+  
+  void test_map_iterator_can_edit_data() {
+    std::map<int, int> map{{1, 1}, {2, 2}, {3, 3}};
+    auto rit = make_recursive_iterator(map);
+    std::get<1>(*rit) = 4;
+    TS_ASSERT_EQUALS(map[1], 4);
+  }
+  
+  void test_map_map_iterator_matches_size() {
+    std::map<int, std::map<int, int>> const map{{1, {{1, 1}}}, {2, {{2, 2}, {3, 3}}}};
+    std::vector<std::tuple<int, int, int>> const expected{{1, 1, 1}, {2, 2, 2}, {2, 3, 3}};
+    auto rit = make_recursive_iterator(map);
+    decltype(rit) end{ };
+    TS_ASSERT_EQUALS(std::distance(rit, end), expected.size());
+  }
+  
+  void test_map_map_iterator_matches_data() {
+    std::map<int, std::map<int, int>> const map{{1, {{1, 1}}}, {2, {{2, 2}, {3, 3}}}};
+    std::vector<std::tuple<int, int, int>> const expected{{1, 1, 1}, {2, 2, 2}, {2, 3, 3}};
+    auto rit = make_recursive_iterator(map);
+    for (auto it = expected.begin(), end = expected.end(); it != end; ++it, ++rit) {
+      TS_ASSERT_EQUALS(std::tuple_cat(*it), *rit);
+    }
+  }
+  
+  void test_map_map_iterator_can_edit_data() {
+    std::map<int, std::map<int, int>> map{{1, {{1, 1}}}, {2, {{2, 2}, {3, 3}}}};
+    auto rit = make_recursive_iterator(map);
+    std::get<2>(*rit) = 4;
+    TS_ASSERT_EQUALS(map[1][1], 4);
+  }
+  
+  void test_map_map_bounded_matches_size() {
+    std::map<int, std::map<int, int>> map{{1, {{1, 1}}}, {2, {{2, 2}, {3, 3}}}};
+    auto rit = make_recursive_iterator<1>(map);
+    decltype(rit) end{ };
+    
+    TS_ASSERT_EQUALS(std::distance(rit, end), map.size());
+  }
+  
+  void test_map_map_bounded_matches_data() {
+    std::map<int, std::map<int, int>> map{{1, {{1, 1}}}, {2, {{2, 2}, {3, 3}}}};
+    auto rit = make_recursive_iterator<1>(map);
+    
+    for (auto it = map.begin(), end = map.end(); it != end; ++it, ++rit) {
+      TS_ASSERT_EQUALS(std::tuple_cat(*it), *rit);
+    }
+  }
+
+};

+ 82 - 0
recursive_iterator_one_dimension.t.h

@@ -0,0 +1,82 @@
+//
+//  recursive_iterator.t.h
+//  iterator
+//
+//  Created by Sam Jaffe on 2/17/17.
+//
+
+#pragma once
+
+#include <cxxtest/TestSuite.h>
+
+#include "recursive_iterator.hpp"
+
+class recursive_iterator_one_dimension_TestSuite : public CxxTest::TestSuite {
+public:
+  void test_vector_iterator_matches_size() {
+    std::vector<int> const vec{1, 2, 3, 4, 5};
+    auto rit = make_recursive_iterator(vec);
+    decltype(rit) end{ };
+    TS_ASSERT_EQUALS(std::distance(rit, end), vec.size());
+  }
+  
+  void test_vector_iterator_matches_data() {
+    std::vector<int> const vec{1, 2, 3, 4, 5};
+    auto rit = make_recursive_iterator(vec);
+    
+    for (auto it = vec.begin(), end = vec.end(); it != end; ++it, ++rit) {
+      TS_ASSERT_EQUALS(*it, *rit);
+    }
+  }
+  
+  void test_vector_can_edit_data() {
+    std::vector<int> vec{1, 2, 3, 4, 5};
+    auto rit = make_recursive_iterator(vec);
+    *rit = 6;
+    TS_ASSERT_EQUALS(vec[0], 6);
+  }
+  
+  void test_vector_vector_matches_size() {
+    std::vector<std::vector<int>> const vec{{1, 2}, {3, 4, 5}};
+    std::vector<int> const expected{1, 2, 3, 4, 5};
+    auto rit = make_recursive_iterator(vec);
+    decltype(rit) end{ };
+
+    TS_ASSERT_EQUALS(std::distance(rit, end), expected.size());
+  }
+
+  void test_vector_vector_matches_data() {
+    std::vector<std::vector<int>> const vec{{1, 2}, {3, 4, 5}};
+    std::vector<int> const expected{1, 2, 3, 4, 5};
+    auto rit = make_recursive_iterator(vec);
+    
+    for (auto it = expected.begin(), end = expected.end(); it != end; ++it, ++rit) {
+      TS_ASSERT_EQUALS(*it, *rit);
+    }
+  }
+  
+  void test_vector_vector_can_edit_data() {
+    std::vector<std::vector<int>> vec{{1, 2}, {3, 4, 5}};
+    auto rit = make_recursive_iterator(vec);
+    *rit = 6;
+    TS_ASSERT_EQUALS(vec[0][0], 6);
+  }
+  
+  void test_vector_vector_bounded_matches_size() {
+    std::vector<std::vector<int>> const vec{{1, 2}, {3, 4, 5}};
+    auto rit = make_recursive_iterator<1>(vec);
+    decltype(rit) end{ };
+    
+    TS_ASSERT_EQUALS(std::distance(rit, end), vec.size());
+  }
+
+  void test_vector_vector_bounded_matches_data() {
+    std::vector<std::vector<int>> const vec{{1, 2}, {3, 4, 5}};
+    auto rit = make_recursive_iterator<1>(vec);
+
+    for (auto it = vec.begin(), end = vec.end(); it != end; ++it, ++rit) {
+      TS_ASSERT_EQUALS(*it, *rit);
+    }
+  }
+
+};