Forráskód Böngészése

Creating a recursive iterator type.
Currently in the form of two different types -
recursive_iterator dives into non-associative containers
flatten_iterator dives into associative contains

This code will be merged once the two have been combined

Samuel Jaffe 8 éve
szülő
commit
0910ad0ac5

+ 5 - 0
end_aware_iterator.hpp

@@ -7,8 +7,11 @@
 
 #pragma once
 
+#include "iterator_fwd.hpp"
+
 #include <iterator>
 
+namespace iterator {
 template <typename Iterator>
 class end_aware_iterator {
 public:
@@ -19,6 +22,7 @@ public:
   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>
@@ -55,3 +59,4 @@ public:
 private:
   iter_type curr_, end_;
 };
+}

+ 1 - 1
end_aware_iterator.t.h

@@ -16,7 +16,7 @@
 class end_aware_TestSuite : public CxxTest::TestSuite {
 public:
   using vec_t = std::vector<int>;
-  using ea_iter = end_aware_iterator<vec_t::iterator>;
+  using ea_iter = iterator::end_aware_iterator<vec_t::iterator>;
 public:
   void test_iterator_points_to_same() {
     vec_t v{1, 2, 3, 4, 5};

+ 207 - 0
flatten_iterator.hpp

@@ -0,0 +1,207 @@
+//
+//  flatten_iterator.hpp
+//  iterator
+//
+//  Created by Sam Jaffe on 2/17/17.
+//
+
+#pragma once
+
+#include "iterator_fwd.hpp"
+
+#include <tuple>
+
+namespace iterator {
+namespace detail {  
+  template <typename Iterator>
+  using flatten_iterator_base = end_aware_iterator< Iterator >;
+  
+  template <typename Iterator>
+  class flatten_iterator_terminal : flatten_iterator_base< Iterator > {
+  private:
+    using layer = flatten_iterator_base< Iterator >;
+    using first_type = typename layer::value_type::first_type;
+    using second_type = typename layer::value_type::second_type;
+  public:
+    using value_type = std::tuple<first_type, second_type>;
+    using reference = std::tuple<first_type &, second_type &>;
+//    using pointer = typename layer::pointer;
+    using difference_type = typename layer::difference_type;
+    using iterator_category = typename layer::iterator_category;
+  public:
+    flatten_iterator_terminal() = default;
+    flatten_iterator_terminal(layer v) : layer(v) {}
+    
+    reference operator*() {
+      return layer::operator*();
+    }
+    
+//    pointer operator->() {
+//      return layer::operator->();
+//    }
+    
+    bool operator==(flatten_iterator_terminal const & other) const {
+      return layer::operator==(other);
+    }
+  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 flatten_iterator_layer :
+  flatten_iterator_base< Iterator >,
+  RecursiveIterator_NextLayer {
+  private:
+    using next_layer = RecursiveIterator_NextLayer;
+    using layer = flatten_iterator_base< Iterator >;
+    
+    using key_type = typename layer::value_type::first_type;
+    using cat_value_type = typename next_layer::value_type;
+    using cat_reference = typename next_layer::reference;
+  public:
+    using value_type = decltype(std::tuple_cat(std::make_tuple(std::declval<key_type>()), std::declval<cat_value_type>()));
+    using reference = decltype(std::tuple_cat(std::tie(std::declval<key_type>()), std::declval<cat_reference>()));
+//    using pointer = typename next_layer::pointer;
+    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) });
+      }
+    }
+    
+    reference operator*() {
+      return std::tuple_cat(std::tie(layer::operator*().first), next_layer::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 eat) {
+      static_cast<layer&>(*this) = eat;
+    }
+    
+    bool done() const { return layer::done(); }
+  };
+  
+  template <typename Iterator, std::size_t N, std::size_t Max, typename = void>
+  class bounded_flatten_iterator_impl :
+  public flatten_iterator_terminal< Iterator > {
+  private:
+    using super = flatten_iterator_terminal< Iterator >;
+  public:
+    using super::super;
+  };
+  
+  template <typename Iterator, std::size_t N, std::size_t Max>
+  class bounded_flatten_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_flatten_iterator_impl< mapped_iterator<Iterator>, N+1, Max > > {
+  private:
+    using next_layer = bounded_flatten_iterator_impl< mapped_iterator<Iterator>, N+1, Max >;
+    using super = flatten_iterator_layer< Iterator, next_layer >;
+  public:
+    using super::super;
+  };
+  
+  template <typename Iterator, typename = void>
+  class flatten_iterator_impl : public flatten_iterator_terminal< Iterator > {
+  private:
+    using super = flatten_iterator_terminal< Iterator >;
+  public:
+    using super::super;
+  };
+  
+  template <typename Iterator>
+  class flatten_iterator_impl< Iterator, typename void_t<mapped_iterator<Iterator>>::type > :
+  public flatten_iterator_layer< Iterator, flatten_iterator_impl< mapped_iterator<Iterator> > > {
+  private:
+    using next_layer = flatten_iterator_impl< mapped_iterator<Iterator> >;
+    using super = flatten_iterator_layer< Iterator, next_layer >;
+  public:
+    using super::super;
+  };
+}
+
+template <typename Iterator>
+class flatten_iterator : detail::flatten_iterator_impl< Iterator > {
+private:
+  using super = detail::flatten_iterator_impl< Iterator >;
+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:
+  using super::super;
+  
+  flatten_iterator & operator++() {
+    (void) super::next();
+    return *this;
+  }
+  
+  flatten_iterator operator++(int) {
+    flatten_iterator tmp{*this};
+    (void) super::next();
+    return tmp;
+  }
+  
+  using super::operator*;
+//  using super::operator->;
+  using super::operator==;
+  bool operator!=(flatten_iterator const & other) { return !(operator==(other)); }
+};
+
+template <typename Iterator, std::size_t N>
+class flatten_iterator_n : detail::bounded_flatten_iterator_impl< Iterator, 1, N > {
+private:
+  using super = detail::bounded_flatten_iterator_impl< Iterator, 1, N >;
+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:
+  using super::super;
+  
+  flatten_iterator_n & operator++() {
+    (void) super::next();
+    return *this;
+  }
+  
+  flatten_iterator_n operator++(int) {
+    flatten_iterator_n tmp{*this};
+    (void) super::next();
+    return tmp;
+  }
+  
+  using super::operator*;
+//  using super::operator->;
+  using super::operator==;
+  bool operator!=(flatten_iterator_n const & other) { return !(operator==(other)); }
+};
+}

+ 10 - 1
iterator.xcodeproj/project.pbxproj

@@ -29,6 +29,10 @@
 		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>"; };
+		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>"; };
+		CD7172EB1E57ED390048DFFF /* flatten_iterator.hpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = flatten_iterator.hpp; sourceTree = "<group>"; };
+		CD7172EC1E5897B80048DFFF /* iterator_fwd.hpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = iterator_fwd.hpp; sourceTree = "<group>"; };
 /* End PBXFileReference section */
 
 /* Begin PBXFrameworksBuildPhase section */
@@ -64,6 +68,7 @@
 			children = (
 				CD21AE2F1E4A428D00536178 /* end_aware_iterator.t.h */,
 				CD21AE2A1E4A3EB000536178 /* join_iterator.t.h */,
+				CD7172EA1E57C91D0048DFFF /* recursive_iterator.t.h */,
 				CD21AE291E4A3EB000536178 /* iterator_tc.cpp */,
 			);
 			name = test;
@@ -72,8 +77,11 @@
 		CD21AE281E4A3E8C00536178 /* src */ = {
 			isa = PBXGroup;
 			children = (
+				CD7172EC1E5897B80048DFFF /* iterator_fwd.hpp */,
 				CD21AE2E1E4A3F8E00536178 /* end_aware_iterator.hpp */,
 				CD21AE2C1E4A3EC100536178 /* join_iterator.hpp */,
+				CD7172E91E57C6580048DFFF /* recursive_iterator.hpp */,
+				CD7172EB1E57ED390048DFFF /* flatten_iterator.hpp */,
 			);
 			name = src;
 			sourceTree = "<group>";
@@ -142,7 +150,7 @@
 			);
 			runOnlyForDeploymentPostprocessing = 0;
 			shellPath = /bin/sh;
-			shellScript = "cxxtestgen --error-printer -o iterator_tc.cpp join_iterator.t.h end_aware_iterator.t.h";
+			shellScript = "cxxtestgen --error-printer -o iterator_tc.cpp join_iterator.t.h end_aware_iterator.t.h recursive_iterator.t.h";
 		};
 /* End PBXShellScriptBuildPhase section */
 
@@ -272,6 +280,7 @@
 				CD21AE261E4A3E7900536178 /* Release */,
 			);
 			defaultConfigurationIsVisible = 0;
+			defaultConfigurationName = Release;
 		};
 /* End XCConfigurationList section */
 	};

+ 20 - 0
iterator_fwd.hpp

@@ -0,0 +1,20 @@
+//
+//  iterator_fwd.hpp
+//  iterator
+//
+//  Created by Sam Jaffe on 2/18/17.
+//
+
+#pragma once
+
+namespace iterator {
+  namespace detail {
+    template <typename> struct void_t { using type = void; };
+
+    template <typename IterType>
+    using value_iterator = decltype(std::begin(*std::declval<IterType>()));
+    
+    template <typename IterType>
+    using mapped_iterator = decltype(std::begin(std::declval<IterType>()->second));
+  }
+}

+ 6 - 3
join_iterator.hpp

@@ -7,16 +7,18 @@
 
 #pragma once
 
-#include <iterator>
-
+#include "iterator_fwd.hpp"
 #include "end_aware_iterator.hpp"
 
+#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 = decltype(std::begin(*std::declval<MetaIterator>()));
+  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;
@@ -86,3 +88,4 @@ private:
   end_aware_iterator<join_iter> joiner_;
   end_aware_iterator<iter_type> iterator_;
 };
+}

+ 1 - 1
join_iterator.t.h

@@ -14,7 +14,7 @@ class join_iterator_TestSuite : public CxxTest::TestSuite {
 public:
   using vec_t = std::vector<int>;
   using meta_vec_t = std::vector<vec_t>;
-  using jn_iter = joining_iterator<meta_vec_t::iterator>;
+  using jn_iter = iterator::joining_iterator<meta_vec_t::iterator>;
   
 //  vec_t v{1,2,3,4,5,6};
 //  meta_vec_t mv{{1,2,3},{4,5,6}};

+ 199 - 0
recursive_iterator.hpp

@@ -0,0 +1,199 @@
+//
+//  recursive_iterator.hpp
+//  iterator
+//
+//  Created by Sam Jaffe on 2/17/17.
+//
+
+#pragma once
+
+#include "iterator_fwd.hpp"
+
+namespace iterator {
+namespace detail {  
+  template <typename Iterator>
+  using recursive_iterator_base = end_aware_iterator< Iterator >;
+  
+  template <typename Iterator>
+  class recursive_iterator_terminal : public recursive_iterator_base< Iterator > {
+  private:
+    using layer = recursive_iterator_base< Iterator >;
+  public:
+    using value_type = typename layer::value_type;
+    using reference = typename layer::reference;
+    using pointer = typename layer::pointer;
+    using difference_type = typename layer::difference_type;
+    using iterator_category = typename layer::iterator_category;
+  public:
+    recursive_iterator_terminal() = default;
+    recursive_iterator_terminal(layer v) : layer(v) {}
+    
+    reference operator*() {
+      return layer::operator*();
+    }
+    
+    pointer operator->() {
+      return layer::operator->();
+    }
+    
+    bool operator==(recursive_iterator_terminal const & other) const {
+      return layer::operator==(other);
+    }
+  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) });
+      }
+    }
+    
+    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 eat) {
+      static_cast<layer&>(*this) = eat;
+    }
+    
+    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<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<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>
+class recursive_iterator : detail::recursive_iterator_impl< Iterator > {
+private:
+  using super = detail::recursive_iterator_impl< Iterator >;
+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:
+  using super::super;
+  
+  recursive_iterator & operator++() {
+    (void) super::next();
+    return *this;
+  }
+  
+  recursive_iterator operator++(int) {
+    recursive_iterator tmp{*this};
+    (void) super::next();
+    return tmp;
+  }
+  
+  using super::operator*;
+  using super::operator->;
+  using super::operator==;
+  bool operator!=(recursive_iterator const & other) { return !(operator==(other)); }
+};
+
+template <typename Iterator, std::size_t N>
+class recursive_iterator_n : detail::bounded_recursive_iterator_impl< Iterator, 1, N > {
+private:
+  using super = detail::bounded_recursive_iterator_impl< Iterator, 1, N >;
+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:
+  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;
+  }
+  
+  using super::operator*;
+  using super::operator->;
+  using super::operator==;
+  bool operator!=(recursive_iterator_n const & other) { return !(operator==(other)); }
+};
+}