Просмотр исходного кода

Segregate and shrink names for recursives.

Sam Jaffe 4 лет назад
Родитель
Сommit
1c7d9584a5

+ 0 - 97
include/iterator/detail/flatten_iterator_layer.hpp

@@ -1,97 +0,0 @@
-#pragma once
-
-#include "arrow_proxy.h"
-#include "recursive_iterator_base.hpp"
-#include "recursive_iterator_traits.hpp"
-
-namespace iterator { namespace detail {
-
-  /**
-   * @class flatten_iterator_layer
-   * @brief A single layer for recursing down a nested collection. Represents
-   * associative containers.
-   *
-   * @copydoc recursive_iterator_layer
-   */
-  template <typename Iterator, typename RecursiveIterator_NextLayer>
-  class flatten_iterator_layer : public recursive_iterator_base<Iterator>,
-                                 public RecursiveIterator_NextLayer {
-  public:
-    using super = 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;
-
-  public:
-    flatten_iterator_layer() = default;
-    explicit flatten_iterator_layer(layer v) : flatten_iterator_layer() {
-      assign(v);
-      update();
-    }
-    template <typename OIter, typename Rec>
-    flatten_iterator_layer(flatten_iterator_layer<OIter, Rec> const & other)
-        : layer(static_cast<recursive_iterator_base<OIter> const &>(other)),
-          super(static_cast<Rec const &>(other)) {}
-
-    /**
-     * @brief Concatenate the key in this layer, with the dereferenced data from
-     * the next.
-     *
-     * Due to the use of the next_layer_type metaprogramming, a type such as
-     * std::map<K, std::vector<std::tuple<T1, T2, T3>>> would return a reference
-     * of type std::tuple<K const &, std::tuple<T1, T2, T3>&>, preserving
-     * sub-aggregates of pair/tuple type. Similarly, forward_as_tuple means
-     * even a key-type of pair/tuple will not be unwrapped.
-     */
-    decltype(auto) operator*() const {
-      using next_t =
-          typename next_layer_type<decltype(super::get()),
-                                   typename super::recursive_category>::type;
-      return std::tuple_cat(std::forward_as_tuple(std::get<0>(layer::get())),
-                            next_t(super::get()));
-    }
-
-    /**
-     * Unimplemented because we return an inline constructed type, and tuple
-     * can only be accessed through std::get anyway.
-     */
-    //    auto operator->() const { return detail::arrow_proxy(**this); }
-    void operator->() const;
-
-    bool operator==(flatten_iterator_layer const & other) const {
-      return (static_cast<layer const &>(*this) == other) &&
-             (static_cast<super const &>(*this) == other);
-    }
-
-  protected:
-    decltype(auto) get() const { return **this; }
-
-    /**
-     * @copydoc recursive_iterator_layer::next
-     */
-    void next() {
-      super::next();
-      update();
-    }
-
-    void update() {
-      layer & self = static_cast<layer &>(*this);
-      while (super::at_end() && !(++self).at_end()) {
-        super::assign(make_end_aware_iterator(self->second));
-      }
-    }
-
-    /**
-     * @copydoc recursive_iterator_layer::assign
-     */
-    void assign(layer v) {
-      static_cast<layer &>(*this) = v;
-      if (!v.at_end()) { super::assign(make_end_aware_iterator(v->second)); }
-    }
-
-    using layer::at_end;
-  };
-}}

+ 0 - 180
include/iterator/detail/recursive_iterator_impl.hpp

@@ -1,180 +0,0 @@
-//
-//  recursive_iterator_meta.hpp
-//  iterator
-//
-//  Created by Sam Jaffe on 2/21/17.
-//
-
-#pragma once
-
-#include "flatten_iterator_layer.hpp"
-#include "recursive_iterator_base.hpp"
-#include "recursive_iterator_layer.hpp"
-#include "recursive_iterator_traits.hpp"
-
-namespace iterator { namespace detail {
-  template <typename Iterator, typeclass = typeclass_t<Iterator>::value>
-  class recursive_iterator_impl;
-
-  /**
-   * A bounded_recursive_iterator_impl where N == Max is always a terminal node.
-   */
-  template <typename Iterator, std::size_t N, std::size_t Max,
-            typeclass = std::conditional_t<N == Max, typeclass_t<void>,
-                                           typeclass_t<Iterator>>::value>
-  class bounded_recursive_iterator_impl;
-
-  /**
-   * @class recursive_iterator_impl
-   * @brief The default (terminal) implementation of an unbounded recursive
-   * iterator.
-   *
-   * @see recursive_iterator_base
-   * @tparam Iterator The iterator type being processed, such as
-   * std::vector<int>::iterator
-   */
-  template <typename Iterator>
-  class recursive_iterator_impl<Iterator, typeclass::TERMINAL>
-      : public recursive_iterator_base<Iterator> {
-  public:
-    using super = recursive_iterator_base<Iterator>;
-
-  public:
-    using super::super;
-    recursive_iterator_impl() = default;
-
-  protected:
-    void next() { super::operator++(); }
-    void assign(super eat) { static_cast<super &>(*this) = eat; }
-  };
-
-  /**
-   * @class recursive_iterator_impl
-   *
-   * An SFINAE specialization of bounded_recursive_iterator_impl for
-   * non-associative container types.
-   * @see recursive_iterator_layer
-   */
-  template <typename Iterator>
-  class recursive_iterator_impl<Iterator, typeclass::CONTAINER>
-      : public recursive_iterator_layer<
-            Iterator, recursive_iterator_impl<value_iterator<Iterator>>> {
-  public:
-    using next_layer = recursive_iterator_impl<value_iterator<Iterator>>;
-    using super = recursive_iterator_layer<Iterator, next_layer>;
-
-  public:
-    /**
-     * A special override of operator* that allows collections like
-     * std::vector<std::vector<std::map<K, V>>> still use the value/reference
-     * type of the map. Works only for nested collections with one associative
-     * container at the bottom level.
-     */
-    auto operator*() const -> decltype(*(next_layer &)(*this)) {
-      return next_layer::operator*();
-    }
-    using super::super;
-    recursive_iterator_impl() = default;
-  };
-
-  /**
-   * @class recursive_iterator_impl
-   *
-   * An SFINAE specialization of bounded_recursive_iterator_impl for
-   * associative container types.
-   * @see flatten_iterator_layer
-   */
-  template <typename Iterator>
-  class recursive_iterator_impl<Iterator, typeclass::ASSOCIATIVE_CONTAINER>
-      : public flatten_iterator_layer<
-            Iterator, recursive_iterator_impl<mapped_iterator<Iterator>>> {
-  public:
-    using next_layer = recursive_iterator_impl<mapped_iterator<Iterator>>;
-    using super = flatten_iterator_layer<Iterator, next_layer>;
-
-  public:
-    using super::super;
-    recursive_iterator_impl() = default;
-  };
-
-  /**
-   * @class bounded_recursive_iterator_impl
-   * @brief The default (terminal) implementation of a recursive iterator up to
-   * Max levels deep.
-   *
-   * @see recursive_iterator_base
-   * @tparam Iterator The iterator type being processed, such as
-   * std::vector<int>::iterator
-   * @tparam N The current layer of depth, starts at 1.
-   * @tparam Max The maximum recursive depth to dive down, in case you need to
-   * process some sub-collection in a specific manner.
-   */
-  template <typename Iterator, std::size_t N, std::size_t Max>
-  class bounded_recursive_iterator_impl<Iterator, N, Max, typeclass::TERMINAL>
-      : public recursive_iterator_base<Iterator> {
-  public:
-    using super = recursive_iterator_base<Iterator>;
-
-  public:
-    using super::super;
-    bounded_recursive_iterator_impl() = default;
-
-  protected:
-    void next() { super::operator++(); }
-    void assign(super eat) { static_cast<super &>(*this) = eat; }
-  };
-
-  /**
-   * @class bounded_recursive_iterator_impl
-   *
-   * An SFINAE specialization of bounded_recursive_iterator_impl for
-   * non-associative container types.
-   * @see recursive_iterator_layer
-   */
-  template <typename Iterator, std::size_t N, std::size_t Max>
-  class bounded_recursive_iterator_impl<Iterator, N, Max, typeclass::CONTAINER>
-      : public recursive_iterator_layer<
-            Iterator, bounded_recursive_iterator_impl<value_iterator<Iterator>,
-                                                      N + 1, Max>> {
-  public:
-    using next_layer =
-        bounded_recursive_iterator_impl<value_iterator<Iterator>, N + 1, Max>;
-    using super = recursive_iterator_layer<Iterator, next_layer>;
-
-  public:
-    /**
-     * A special override of operator* that allows collections like
-     * std::vector<std::vector<std::map<K, V>>> still use the value/reference
-     * type of the map. Works only for nested collections with one associative
-     * container at the bottom/Max level.
-     */
-    auto operator*() const -> decltype(*(next_layer &)(*this)) {
-      return next_layer::operator*();
-    }
-    using super::super;
-    bounded_recursive_iterator_impl() = default;
-  };
-
-  /**
-   * @class bounded_recursive_iterator_impl
-   *
-   * An SFINAE specialization of bounded_recursive_iterator_impl for
-   * associative container types.
-   * @see flatten_iterator_layer
-   */
-  template <typename Iterator, std::size_t N, std::size_t Max>
-  class bounded_recursive_iterator_impl<Iterator, N, Max,
-                                        typeclass::ASSOCIATIVE_CONTAINER>
-      : public flatten_iterator_layer<
-            Iterator, bounded_recursive_iterator_impl<mapped_iterator<Iterator>,
-                                                      N + 1, Max>> {
-  public:
-    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;
-    bounded_recursive_iterator_impl() = default;
-  };
-}}

+ 0 - 82
include/iterator/detail/recursive_iterator_layer.hpp

@@ -1,82 +0,0 @@
-#pragma once
-
-#include "recursive_iterator_base.hpp"
-#include "recursive_iterator_traits.hpp"
-
-namespace iterator { namespace detail {
-  /**
-   * @class recursive_iterator_layer
-   * @brief A single layer for recursing down a nested collection. Represents
-   * non-associative containers.
-   *
-   * Provides dispatch/overloading for types and functions of recursive_iterator
-   * chains to resolve ambiguous typedefs and operators.
-   *
-   * @see recursive_iterator_impl
-   * @see bounded_recursive_iterator_impl
-   * @tparam Iterator The underlying iterator type of the layer
-   * @tparam RecursiveIterator_NextLayer The next layer, either a
-   * recursive_iterator_impl, or a bounded_recursive_iterator_impl
-   */
-  template <typename Iterator, typename RecursiveIterator_NextLayer>
-  class recursive_iterator_layer : public recursive_iterator_base<Iterator>,
-                                   public RecursiveIterator_NextLayer {
-  public:
-    using super = RecursiveIterator_NextLayer;
-    using layer = recursive_iterator_base<Iterator>;
-
-  protected:
-    using recursive_category = continue_layer_tag_t;
-
-  public:
-    recursive_iterator_layer() = default;
-    explicit recursive_iterator_layer(layer v) : recursive_iterator_layer() {
-      assign(v);
-      update();
-    }
-    template <typename OIter, typename Rec>
-    recursive_iterator_layer(recursive_iterator_layer<OIter, Rec> const & other)
-        : layer(static_cast<recursive_iterator_base<OIter> const &>(other)),
-          super(static_cast<Rec const &>(other)) {}
-
-    decltype(auto) operator*() const { return super::get(); }
-    decltype(auto) operator->() const { return super::operator->(); }
-
-    bool operator==(recursive_iterator_layer const & other) const {
-      return (static_cast<layer const &>(*this) == other) &&
-             (static_cast<super const &>(*this) == other);
-    }
-
-  protected:
-    decltype(auto) get() const { return operator*(); }
-
-    /**
-     * Advance the iterator step. If the next layer has reached the end, then
-     * we advance this iterator until it reaches either its own end, or a
-     * non-empty subcollection to start iterating over.
-     */
-    void next() {
-      super::next();
-      update();
-    }
-
-    /**
-     * Update the underlying iterator and propogate updates down the chain so
-     * that if there is data available, the iterator is in a dereferencable
-     * state.
-     */
-    void assign(layer v) {
-      static_cast<layer &>(*this) = v;
-      if (!v.at_end()) { super::assign(make_end_aware_iterator(*v)); }
-    }
-
-    void update() {
-      layer & self = static_cast<layer &>(*this);
-      while (super::at_end() && !(++self).at_end()) {
-        super::assign(make_end_aware_iterator(*self));
-      }
-    }
-
-    using layer::at_end;
-  };
-}}

+ 8 - 8
include/iterator/detail/recursive_iterator_base.hpp

@@ -1,32 +1,32 @@
 #pragma once
 
 #include "../end_aware_iterator.hpp"
-#include "recursive_iterator_traits.hpp"
+#include "traits.hpp"
 
-namespace iterator::detail {
+namespace iterator::recursive {
   /**
    * @class recursive_iterator_base
    * @brief A thin wrapper around end_aware_iterator for the purposes of
    * template metaprogramming.
    */
   template <typename Iterator>
-  class recursive_iterator_base : public end_aware_iterator<Iterator> {
+  class base : public end_aware_iterator<Iterator> {
   public:
     using super = end_aware_iterator<Iterator>;
 
   protected:
     using recursive_category =
-        std::conditional_t<detail::is_associative<Iterator>{},
-                           continue_layer_tag_t, terminal_layer_tag_t>;
+        std::conditional_t<is_associative<Iterator>{}, continue_layer_tag_t,
+                           terminal_layer_tag_t>;
 
   public:
     using super::super;
-    recursive_iterator_base(super const & iter) : super(iter) {}
-    recursive_iterator_base(super && iter) : super(std::move(iter)) {}
+    base(super const & iter) : super(iter) {}
+    base(super && iter) : super(std::move(iter)) {}
 
   protected:
     decltype(auto) get() const {
-      if constexpr (detail::is_associative<Iterator>{}) {
+      if constexpr (is_associative<Iterator>{}) {
         return std::tie((**this).first, (**this).second);
       } else {
         return **this;

+ 91 - 0
include/iterator/recursive/flatten_layer.hpp

@@ -0,0 +1,91 @@
+#pragma once
+
+#include "../detail/arrow_proxy.h"
+#include "base.hpp"
+#include "traits.hpp"
+
+namespace iterator::recursive {
+
+  /**
+   * @class flatten_iterator_layer
+   * @brief A single layer for recursing down a nested collection. Represents
+   * associative containers.
+   *
+   * @copydoc recursive_iterator_layer
+   */
+  template <typename Iterator, typename Next>
+  class flatten_layer : public base<Iterator>, public Next {
+  protected:
+    using recursive_category = continue_layer_tag_t;
+
+  public:
+    flatten_layer() = default;
+    explicit flatten_layer(base<Iterator> v) : flatten_layer() {
+      assign(v);
+      update();
+    }
+    template <typename OIter, typename Rec>
+    flatten_layer(flatten_layer<OIter, Rec> const & other)
+        : base<Iterator>(static_cast<base<OIter> const &>(other)),
+          Next(static_cast<Rec const &>(other)) {}
+
+    /**
+     * @brief Concatenate the key in this layer, with the dereferenced data from
+     * the next.
+     *
+     * Due to the use of the next_layer_type metaprogramming, a type such as
+     * std::map<K, std::vector<std::tuple<T1, T2, T3>>> would return a reference
+     * of type std::tuple<K const &, std::tuple<T1, T2, T3>&>, preserving
+     * sub-aggregates of pair/tuple type. Similarly, forward_as_tuple means
+     * even a key-type of pair/tuple will not be unwrapped.
+     */
+    decltype(auto) operator*() const {
+      using next_t =
+          typename next_layer_type<decltype(Next::get()),
+                                   typename Next::recursive_category>::type;
+      return std::tuple_cat(
+          std::forward_as_tuple(std::get<0>(base<Iterator>::get())),
+          next_t(Next::get()));
+    }
+
+    /**
+     * Unimplemented because we return an inline constructed type, and tuple
+     * can only be accessed through std::get anyway.
+     */
+    //    auto operator->() const { return detail::arrow_proxy(**this); }
+    void operator->() const;
+
+    bool operator==(flatten_layer const & other) const {
+      return (static_cast<base<Iterator> const &>(*this) == other) &&
+             (static_cast<Next const &>(*this) == other);
+    }
+
+  protected:
+    decltype(auto) get() const { return **this; }
+
+    /**
+     * @copydoc recursive_iterator_layer::next
+     */
+    void next() {
+      Next::next();
+      update();
+    }
+
+    void update() {
+      base<Iterator> & self = static_cast<base<Iterator> &>(*this);
+      while (Next::at_end() && !(++self).at_end()) {
+        Next::assign(make_end_aware_iterator(self->second));
+      }
+    }
+
+    /**
+     * @copydoc recursive_iterator_layer::assign
+     */
+    void assign(base<Iterator> v) {
+      static_cast<base<Iterator> &>(*this) = v;
+      if (!v.at_end()) { Next::assign(make_end_aware_iterator(v->second)); }
+    }
+
+    using base<Iterator>::at_end;
+  };
+}

+ 171 - 0
include/iterator/recursive/impl.hpp

@@ -0,0 +1,171 @@
+//
+//  impl.hpp
+//  iterator
+//
+//  Created by Sam Jaffe on 2/21/17.
+//
+
+#pragma once
+
+#include "base.hpp"
+#include "flatten_layer.hpp"
+#include "layer.hpp"
+#include "traits.hpp"
+
+namespace iterator::recursive {
+  template <typename Iterator, typeclass = typeclass_t<Iterator>::value>
+  class impl;
+
+  /**
+   * A bounded_impl where N == Max is always a terminal node.
+   */
+  template <typename Iterator, std::size_t N, std::size_t Max,
+            typeclass = std::conditional_t<N == Max, typeclass_t<void>,
+                                           typeclass_t<Iterator>>::value>
+  class bounded_impl;
+
+  /**
+   * @class impl
+   * @brief The default (terminal) implementation of an unbounded recursive
+   * iterator.
+   *
+   * @see base
+   * @tparam Iterator The iterator type being processed, such as
+   * std::vector<int>::iterator
+   */
+  template <typename Iterator>
+  class impl<Iterator, typeclass::TERMINAL> : public base<Iterator> {
+  public:
+    using super = base<Iterator>;
+
+  public:
+    using super::super;
+    impl() = default;
+
+  protected:
+    void next() { super::operator++(); }
+    void assign(super eat) { static_cast<super &>(*this) = eat; }
+  };
+
+  /**
+   * @class impl
+   *
+   * An SFINAE specialization of bounded_impl for
+   * non-associative container types.
+   * @see layer
+   */
+  template <typename Iterator>
+  class impl<Iterator, typeclass::CONTAINER>
+      : public layer<Iterator, impl<value<Iterator>>> {
+  public:
+    using next_layer = impl<value<Iterator>>;
+    using super = layer<Iterator, next_layer>;
+
+  public:
+    /**
+     * A special override of operator* that allows collections like
+     * std::vector<std::vector<std::map<K, V>>> still use the value/reference
+     * type of the map. Works only for nested collections with one associative
+     * container at the bottom level.
+     */
+    auto operator*() const -> decltype(*(next_layer &)(*this)) {
+      return next_layer::operator*();
+    }
+    using super::super;
+    impl() = default;
+  };
+
+  /**
+   * @class impl
+   *
+   * An SFINAE specialization of bounded_impl for
+   * associative container types.
+   * @see flatten_iterator_layer
+   */
+  template <typename Iterator>
+  class impl<Iterator, typeclass::ASSOCIATIVE_CONTAINER>
+      : public flatten_layer<Iterator, impl<mapped<Iterator>>> {
+  public:
+    using next_layer = impl<mapped<Iterator>>;
+    using super = flatten_layer<Iterator, next_layer>;
+
+  public:
+    using super::super;
+    impl() = default;
+  };
+
+  /**
+   * @class bounded_impl
+   * @brief The default (terminal) implementation of a recursive iterator up to
+   * Max levels deep.
+   *
+   * @see base
+   * @tparam Iterator The iterator type being processed, such as
+   * std::vector<int>::iterator
+   * @tparam N The current layer of depth, starts at 1.
+   * @tparam Max The maximum recursive depth to dive down, in case you need to
+   * process some sub-collection in a specific manner.
+   */
+  template <typename Iterator, std::size_t N, std::size_t Max>
+  class bounded_impl<Iterator, N, Max, typeclass::TERMINAL>
+      : public base<Iterator> {
+  public:
+    using super = base<Iterator>;
+
+  public:
+    using super::super;
+    bounded_impl() = default;
+
+  protected:
+    void next() { super::operator++(); }
+    void assign(super eat) { static_cast<super &>(*this) = eat; }
+  };
+
+  /**
+   * @class bounded_impl
+   *
+   * An SFINAE specialization of bounded_impl for
+   * non-associative container types.
+   * @see layer
+   */
+  template <typename Iterator, std::size_t N, std::size_t Max>
+  class bounded_impl<Iterator, N, Max, typeclass::CONTAINER>
+      : public layer<Iterator, bounded_impl<value<Iterator>, N + 1, Max>> {
+  public:
+    using next_layer = bounded_impl<value<Iterator>, N + 1, Max>;
+    using super = layer<Iterator, next_layer>;
+
+  public:
+    /**
+     * A special override of operator* that allows collections like
+     * std::vector<std::vector<std::map<K, V>>> still use the value/reference
+     * type of the map. Works only for nested collections with one associative
+     * container at the bottom/Max level.
+     */
+    auto operator*() const -> decltype(*(next_layer &)(*this)) {
+      return next_layer::operator*();
+    }
+    using super::super;
+    bounded_impl() = default;
+  };
+
+  /**
+   * @class bounded_impl
+   *
+   * An SFINAE specialization of bounded_impl for
+   * associative container types.
+   * @see flatten_iterator_layer
+   */
+  template <typename Iterator, std::size_t N, std::size_t Max>
+  class bounded_impl<Iterator, N, Max, typeclass::ASSOCIATIVE_CONTAINER>
+      : public flatten_layer<Iterator,
+                             bounded_impl<mapped<Iterator>, N + 1, Max>> {
+  public:
+    using next_layer = bounded_impl<mapped<Iterator>, N + 1, Max>;
+    using super = flatten_layer<Iterator, next_layer>;
+
+  public:
+    using super::super;
+    bounded_impl() = default;
+  };
+}

+ 77 - 0
include/iterator/recursive/layer.hpp

@@ -0,0 +1,77 @@
+#pragma once
+
+#include "base.hpp"
+#include "traits.hpp"
+
+namespace iterator::recursive {
+  /**
+   * @class recursive_iterator_layer
+   * @brief A single layer for recursing down a nested collection. Represents
+   * non-associative containers.
+   *
+   * Provides dispatch/overloading for types and functions of recursive_iterator
+   * chains to resolve ambiguous typedefs and operators.
+   *
+   * @see recursive_iterator_impl
+   * @see bounded_recursive_iterator_impl
+   * @tparam Iterator The underlying iterator type of the layer
+   * @tparam Next The next layer, either a
+   * recursive_iterator_impl, or a bounded_recursive_iterator_impl
+   */
+  template <typename Iterator, typename Next>
+  class layer : public base<Iterator>, public Next {
+  protected:
+    using recursive_category = continue_layer_tag_t;
+
+  public:
+    layer() = default;
+    explicit layer(base<Iterator> v) : layer() {
+      assign(v);
+      update();
+    }
+    template <typename OIter, typename Rec>
+    layer(layer<OIter, Rec> const & other)
+        : base<Iterator>(static_cast<base<OIter> const &>(other)),
+          Next(static_cast<Rec const &>(other)) {}
+
+    decltype(auto) operator*() const { return Next::get(); }
+    decltype(auto) operator->() const { return Next::operator->(); }
+
+    bool operator==(layer const & other) const {
+      return (static_cast<base<Iterator> const &>(*this) == other) &&
+             (static_cast<Next const &>(*this) == other);
+    }
+
+  protected:
+    decltype(auto) get() const { return operator*(); }
+
+    /**
+     * Advance the iterator step. If the next layer has reached the end, then
+     * we advance this iterator until it reaches either its own end, or a
+     * non-empty subcollection to start iterating over.
+     */
+    void next() {
+      Next::next();
+      update();
+    }
+
+    /**
+     * Update the underlying iterator and propogate updates down the chain so
+     * that if there is data available, the iterator is in a dereferencable
+     * state.
+     */
+    void assign(base<Iterator> v) {
+      static_cast<base<Iterator> &>(*this) = v;
+      if (!v.at_end()) { Next::assign(make_end_aware_iterator(*v)); }
+    }
+
+    void update() {
+      base<Iterator> & self = static_cast<base<Iterator> &>(*this);
+      while (Next::at_end() && !(++self).at_end()) {
+        Next::assign(make_end_aware_iterator(*self));
+      }
+    }
+
+    using base<Iterator>::at_end;
+  };
+}

+ 15 - 24
include/iterator/detail/recursive_iterator_traits.hpp

@@ -5,14 +5,12 @@
 #include <tuple>
 #include <utility>
 
+#include "../detail/traits.h"
 #include "../iterator_fwd.hpp"
-#include "traits.h"
 
-namespace iterator { namespace detail {
-  template <typename Iterator, typename RecursiveIterator_NextLayer>
-  class flatten_iterator_layer;
-  template <typename Iterator, typename RecursiveIterator_NextLayer>
-  class recursive_iterator_layer;
+namespace iterator::recursive {
+  template <typename Iterator, typename Next> class flatten_layer;
+  template <typename Iterator, typename Next> class layer;
 
   // Helper struct for dealing with merging output from associative and
   // non-associative containers.
@@ -30,11 +28,10 @@ namespace iterator { namespace detail {
 
   // Helpers for condensing type deductions
   template <typename IterType>
-  using value_iterator = decltype(std::begin(*std::declval<IterType>()));
+  using value = decltype(std::begin(*std::declval<IterType>()));
 
   template <typename IterType>
-  using mapped_iterator =
-      decltype(std::begin(std::declval<IterType>()->second));
+  using mapped = decltype(std::begin(std::declval<IterType>()->second));
 
   // Type trait to identify value_type ~~ std::pair<K const, V>, which is
   // a safe bet towards 'this is an associative container type'
@@ -45,9 +42,6 @@ namespace iterator { namespace detail {
                                typename T::value_type::first_type>::value>>
       : std::true_type {};
 
-  template <typename T>
-  using is_associative_t = std::enable_if_t<is_associative<T>::value>;
-
   // Type deduction guides for constructing recursive iterators.
   enum class typeclass { TERMINAL, CONTAINER, ASSOCIATIVE_CONTAINER };
 
@@ -62,18 +56,17 @@ namespace iterator { namespace detail {
   struct is_string_iterator<std::string::const_iterator> : std::true_type {};
 
   template <typename T>
-  struct typeclass_t<
-      T, std::enable_if_t<!is_string_iterator<value_iterator<T>>::value>> {
+  struct typeclass_t<T,
+                     std::enable_if_t<!is_string_iterator<value<T>>::value>> {
     static constexpr typeclass const value{typeclass::CONTAINER};
   };
 
   template <typename T>
-  struct typeclass_t<
-      T, std::enable_if_t<is_string_iterator<value_iterator<T>>::value>> {
+  struct typeclass_t<T, std::enable_if_t<is_string_iterator<value<T>>::value>> {
     static constexpr typeclass const value{typeclass::TERMINAL};
   };
 
-  template <typename T> struct typeclass_t<T, void_t<mapped_iterator<T>>> {
+  template <typename T> struct typeclass_t<T, detail::void_t<mapped<T>>> {
     static constexpr typeclass const value{typeclass::ASSOCIATIVE_CONTAINER};
   };
 
@@ -84,13 +77,12 @@ namespace iterator { namespace detail {
     using type = end_aware_iterator<It>;
   };
 
-  template <typename It, typename Rec>
-  struct accessor<0, recursive_iterator_layer<It, Rec>> {
+  template <typename It, typename Rec> struct accessor<0, layer<It, Rec>> {
     using type = end_aware_iterator<It>;
   };
 
   template <typename It, typename Rec>
-  struct accessor<0, flatten_iterator_layer<It, Rec>> {
+  struct accessor<0, flatten_layer<It, Rec>> {
     using type = end_aware_iterator<It>;
   };
 
@@ -104,15 +96,14 @@ namespace iterator { namespace detail {
   };
 
   template <std::size_t I, typename It, typename Rec>
-  struct accessor<I, recursive_iterator_layer<It, Rec>,
-                  typename std::enable_if<I != 0>::type> {
+  struct accessor<I, layer<It, Rec>, typename std::enable_if<I != 0>::type> {
     using type = typename accessor<I - 1, Rec>::type;
   };
 
   template <std::size_t I, typename It, typename Rec>
-  struct accessor<I, flatten_iterator_layer<It, Rec>,
+  struct accessor<I, flatten_layer<It, Rec>,
                   typename std::enable_if<I != 0>::type> {
     using type = typename accessor<I - 1, Rec>::type;
   };
 
-}}
+}

+ 8 - 10
include/iterator/recursive_iterator.hpp

@@ -9,10 +9,9 @@
 
 #include <tuple>
 
-#include "detail/recursive_iterator_impl.hpp"
-#include "detail/recursive_iterator_traits.hpp"
-#include "detail/traits.h"
 #include "iterator_fwd.hpp"
+#include "recursive/impl.hpp"
+#include "recursive/traits.hpp"
 
 namespace iterator {
   /**
@@ -29,9 +28,9 @@ namespace iterator {
    * @tparam Iterator The iterator type of the top-level collection.
    */
   template <typename Iterator>
-  class recursive_iterator : public detail::recursive_iterator_impl<Iterator> {
+  class recursive_iterator : public recursive::impl<Iterator> {
   public:
-    using super = detail::recursive_iterator_impl<Iterator>;
+    using super = recursive::impl<Iterator>;
     using reference = decltype(*std::declval<super>());
     using value_type = std::remove_cv_t<std::remove_reference_t<reference>>;
     using pointer = decltype(std::declval<super>().operator->());
@@ -77,10 +76,9 @@ namespace iterator {
    * @tparam N The maximum depth to recurse into the object
    */
   template <typename Iterator, std::size_t N>
-  class recursive_iterator_n
-      : public detail::bounded_recursive_iterator_impl<Iterator, 1, N> {
+  class recursive_iterator_n : public recursive::bounded_impl<Iterator, 1, N> {
   public:
-    using super = detail::bounded_recursive_iterator_impl<Iterator, 1, N>;
+    using super = recursive::bounded_impl<Iterator, 1, N>;
     using reference = decltype(*std::declval<super>());
     using value_type = std::remove_cv_t<std::remove_reference_t<reference>>;
     using pointer = decltype(std::declval<super>().operator->());
@@ -111,14 +109,14 @@ namespace iterator {
 namespace std {
   template <std::size_t I, typename It>
   auto get(::iterator::recursive_iterator<It> const & iter) ->
-      typename ::iterator::detail::accessor<
+      typename ::iterator::recursive::accessor<
           I, ::iterator::recursive_iterator<It>>::type {
     return iter;
   }
 
   template <std::size_t I, typename It, std::size_t N>
   auto get(::iterator::recursive_iterator_n<It, N> const & iter) ->
-      typename ::iterator::detail::accessor<
+      typename ::iterator::recursive::accessor<
           I, ::iterator::recursive_iterator_n<It, N>>::type {
     static_assert(I < N, "Cannot get past bounding level");
     return iter;