#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 class layer : public base, public Next { protected: using recursive_category = continue_layer_tag_t; public: layer() = default; explicit layer(base v) : layer() { assign(v); update(); } template layer(layer const & other) : base(static_cast const &>(other)), Next(static_cast(other)) {} decltype(auto) operator*() const { return Next::get(); } decltype(auto) operator->() const { return Next::operator->(); } bool operator==(layer const & other) const { return (static_cast const &>(*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() { 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 v) { static_cast &>(*this) = v; if (!v.at_end()) { Next::assign(make_end_aware_iterator(*v)); } } void update() { base & self = static_cast &>(*this); while (Next::at_end() && !(++self).at_end()) { Next::assign(make_end_aware_iterator(*self)); } } using base::at_end; }; }