#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: recursive_iterator_layer() = default; explicit 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)) {} 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(*this) == other) && (static_cast(*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(*this) = v; if (!v.at_end()) { super::assign(make_end_aware_iterator(*v)); } } void update() { layer & self = static_cast(*this); while (super::at_end() && !(++self).at_end()) { super::assign(make_end_aware_iterator(*self)); } } using layer::at_end; }; }}