#pragma once #include "../end_aware_iterator.hpp" #include "recursive_iterator_traits.hpp" namespace iterator { namespace detail { template class recursive_iterator_base; /** * @class recursive_iterator_base * @brief A thin wrapper around end_aware_iterator for the purposes of * template metaprogramming. */ template class recursive_iterator_base : public end_aware_iterator { public: using super = end_aware_iterator; protected: using recursive_category = 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)) {} recursive_iterator_base() = default; protected: typename super::reference get() const { return super::operator*(); } }; /** * @class recursive_iterator_base * @brief An SFINAE specialization of recursive_iterator_base for associative * containers * * Because it is possible for recursive iterator to step over multiple layers * of associative containers, the return type is made into a tuple, so that * the caller does not need to write something like * `it->second.second.second'. Instead, the return type is a tuple of * references, so that the caller can write code like `std::get<3>(*it)'. * * For example, the ref type for std::map > * with this would be std::tuple. */ template class recursive_iterator_base> : public end_aware_iterator { public: using super = end_aware_iterator; using first_type = decltype((std::declval()->first)); using second_type = decltype((std::declval()->second)); protected: using recursive_category = continue_layer_tag_t; public: using value_type = std::tuple; using reference = std::tuple; public: using super::super; recursive_iterator_base(super const & iter) : super(iter) {} recursive_iterator_base(super && iter) : super(std::move(iter)) {} recursive_iterator_base() = default; protected: /** * An alternative function to operator*(), which allows single layer * recursive iterators (on associative containers) to return the * underlying value/reference type, and nested containers to propogate * a tuple or a pair as necessary. */ reference get() const { auto & pair = super::operator*(); return std::tie(pair.first, pair.second); } }; }}