#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 class recursive_iterator_layer : public recursive_iterator_base, public RecursiveIterator_NextLayer { public: using super = RecursiveIterator_NextLayer; using layer = recursive_iterator_base; protected: using recursive_category = continue_layer_tag_t; 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 = std::forward_iterator_tag; public: recursive_iterator_layer() = default; recursive_iterator_layer(layer v) : recursive_iterator_layer() { assign(v); update(); } template recursive_iterator_layer(recursive_iterator_layer const & other) : layer(static_cast const &>(other)), super(static_cast(other)) {} reference operator*() const { return super::get(); } pointer operator->() const { return super::operator->(); } bool operator==(recursive_iterator_layer const & other) const { return layer::operator==(other) && super::operator==(other); } protected: reference 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(*this) = v; if (!v.done()) { super::assign(make_end_aware_iterator(*v)); } } void update() { layer & self = static_cast(*this); while (super::done() && !(++self).done()) { super::assign(make_end_aware_iterator(*self)); } } bool done() const { return layer::done(); } }; }}