浏览代码

Move shared behavior of trie_iterator (Pre-Order) and trie_reverse_iterator (Inverse-Depth-First) iteration to an object in the detail namespace.

LoC are not reduced significantly, but shared code snippets are all de-duplicated.
Samuel Jaffe 8 年之前
父节点
当前提交
b811336b99
共有 2 个文件被更改,包括 75 次插入87 次删除
  1. 1 1
      trie.t.h
  2. 74 86
      trie_iterator.hpp

+ 1 - 1
trie.t.h

@@ -42,7 +42,7 @@ public:
     TS_ASSERT_EQUALS(++it, end);
   }
 
-  void testReverseIterationIsPostOrder() {
+  void testReverseIterationIsInvDepthFirst() {
     auto it = data.crbegin();
     TS_ASSERT_EQUALS(*it, 2);
     TS_ASSERT_EQUALS(*++it, 4);

+ 74 - 86
trie_iterator.hpp

@@ -28,12 +28,61 @@ namespace detail {
       return { tr.local_rbegin(), tr.local_rend() };
     }
   };
+  
+  template <typename Trie, typename V, typename Iter>
+  class trie_iterator_base {
+  protected:
+    using impl_t = ::iterator::end_aware_iterator<Iter>;
+  public:
+    trie_iterator_base() : done{true} {}
+    trie_iterator_base(Trie * tr) { stk.push(tr); }
+    V & operator*() const { return *stk.top(); }
+  protected:
+    bool poping_empty() {
+      if (iters.top().done()) {
+        stk.pop();
+        iters.pop();
+        keys.pop_back();
+        return !iters.empty();
+      }
+      return false;
+    }
+    void assign() {
+      if (!iters.empty()) {
+        stk.top() = iters.top()->second.get();
+        keys.back() = iters.top()->first;
+      }
+    }
+    bool can_recurse() { return !next().done(); }
+    void recurse() {
+      auto it = next();
+      iters.push(it);
+      keys.push_back(it->first);
+      stk.push(it->second.get());
+    }
+    impl_t next() { return detail::trie_iterator_next<Iter>()(*stk.top()); }
+    friend bool operator!=(trie_iterator_base const & lhs, trie_iterator_base const & rhs) {
+      return !(lhs == rhs);
+    }
+    friend bool operator==(trie_iterator_base const & lhs, trie_iterator_base const & rhs) {
+      if ( lhs.done && rhs.done ) return true;
+      else if (lhs.keys != rhs.keys) return false;
+      else if ( lhs.done != rhs.done ) return false;
+      else return *lhs == *rhs;
+    }
+  protected:
+    friend Trie;
+    std::stack<Trie *> stk;
+    std::list<typename Trie::key_type> keys;
+    std::stack<impl_t> iters;
+    bool done{false};
+  };
 }
 
 template <typename Trie, typename V, typename Iter>
-class trie_iterator {
+class trie_iterator : public detail::trie_iterator_base<Trie, V, Iter> {
 private:
-  using impl_t = ::iterator::end_aware_iterator<Iter>;
+  using super = detail::trie_iterator_base<Trie, V, Iter>;
 public:
   using value_type = V;
   using reference = value_type &;
@@ -41,60 +90,30 @@ public:
   using difference_type = std::ptrdiff_t;
   using iterator_category = std::forward_iterator_tag;
 public:
-  trie_iterator() : done{true} {}
-  trie_iterator(Trie * tr) { stk.push(tr); }
-  reference operator*() const { return *stk.top(); }
+  trie_iterator() : super() {}
+  trie_iterator(Trie * tr) : super(tr) { }
   trie_iterator & operator++() {
-    if (done) return *this;
-    if ( iters.empty() || can_recurse() ) { recurse(); }
+    if (super::done) return *this;
+    if ( super::iters.empty() || super::can_recurse() ) { super::recurse(); }
     else { advance(); }
     return *this;
   }
 private:
-  bool can_recurse() { return !next().done(); }
-  void recurse() {
-    auto it = next();
-    iters.push(it);
-    keys.push_back(it->first);
-    stk.push(it->second.get());
-  }
-  impl_t next() { return detail::trie_iterator_next<Iter>()(*stk.top()); }
   void advance() {
-    ++iters.top();
-    while (iters.top().done()) {
-      stk.pop();
-      iters.pop();
-      keys.pop_back();
-      if ( iters.empty() ) break;
-      ++iters.top();
+    ++super::iters.top();
+    while (super::poping_empty()) {
+      ++super::iters.top();
     }
-    if (!iters.empty()) {
-      stk.top() = iters.top()->second.get();
-      keys.back() = iters.top()->first;
-    } else {
-      done = true;
-    }
-  }
-  friend bool operator!=(trie_iterator const & lhs, trie_iterator const & rhs) {
-    return !(lhs == rhs);
-  }
-  friend bool operator==(trie_iterator const & lhs, trie_iterator const & rhs) {
-    if ( lhs.done && rhs.done ) return true;
-    else if (lhs.keys != rhs.keys) return false;
-    else if ( lhs.done != rhs.done ) return false;
-    else return *lhs == *rhs;
+    super::assign();
+    super::done = super::iters.empty();
   }
   friend Trie;
-  std::stack<Trie *> stk;
-  std::list<typename Trie::key_type> keys;
-  std::stack<impl_t> iters;
-  bool done{false};
 };
 
 template <typename Trie, typename V, typename Iter>
-class trie_reverse_iterator {
+class trie_reverse_iterator : public detail::trie_iterator_base<Trie, V, Iter> {
 private:
-  using impl_t = ::iterator::end_aware_iterator<Iter>;
+  using super = detail::trie_iterator_base<Trie, V, Iter>;
 public:
   using value_type = V;
   using reference = value_type &;
@@ -102,59 +121,28 @@ public:
   using difference_type = std::ptrdiff_t;
   using iterator_category = std::forward_iterator_tag;
 public:
-  trie_reverse_iterator() : done{true} {}
-  trie_reverse_iterator(Trie * tr) {
-    stk.push(tr);
-    if (can_recurse()) recurse();
+  trie_reverse_iterator() : super() {}
+  trie_reverse_iterator(Trie * tr) : super(tr) {
+    if (super::can_recurse()) recurse();
   }
-  reference operator*() const { return *stk.top(); }
   trie_reverse_iterator & operator++() {
-    if (done || iters.empty()) { done = true; return *this; }
-    advance();
+    if (super::done || super::iters.empty()) { super::done = true; }
+    else { advance(); }
     return *this;
   }
 private:
-  bool can_recurse() { return !next().done(); }
   void recurse() {
-    do {
-      auto it = next();
-      iters.push(it);
-      keys.push_back(it->first);
-      stk.push(it->second.get());
-    } while ( can_recurse() );
+    do { super::recurse(); } while ( super::can_recurse() );
   }
-  impl_t next() { return detail::trie_iterator_next<Iter>()(*stk.top()); }
   void advance() {
-    ++iters.top();
-    if (iters.top().done()) {
-      while (iters.top().done()) {
-        stk.pop();
-        iters.pop();
-        keys.pop_back();
-        if ( iters.empty() ) break;
-      }
-      if (!iters.empty()) {
-        stk.top() = iters.top()->second.get();
-        keys.back() = iters.top()->first;
-      }
+    ++super::iters.top();
+    if (super::iters.top().done()) {
+      while (super::poping_empty());
+      super::assign();
     } else {
-      stk.top() = iters.top()->second.get();
-      keys.back() = iters.top()->first;
-      if (can_recurse()) recurse();
+      super::assign();
+      if (super::can_recurse()) recurse();
     }
   }
-  friend bool operator!=(trie_reverse_iterator const & lhs, trie_reverse_iterator const & rhs) {
-    return !(lhs == rhs);
-  }
-  friend bool operator==(trie_reverse_iterator const & lhs, trie_reverse_iterator const & rhs) {
-    if ( lhs.done && rhs.done ) return true;
-    else if (lhs.keys != rhs.keys) return false;
-    else if ( lhs.done != rhs.done ) return false;
-    else return *lhs == *rhs;
-  }
   friend Trie;
-  std::stack<Trie *> stk;
-  std::list<typename Trie::key_type> keys;
-  std::stack<impl_t> iters;
-  bool done{false};
 };