// // recursive_iterator.hpp // iterator // // Created by Sam Jaffe on 2/17/17. // #pragma once #include #include "detail/recursive_iterator_impl.hpp" #include "detail/recursive_iterator_traits.hpp" #include "iterator_fwd.hpp" namespace iterator { /** * @class recursive_iterator * @brief An iterator type for nested collections, allowing you to treat it as * a single-layer collection. * * In order to provide a simple interface, if an associative container is used * in the chain, the type returned by operator*() is a tuple. If multiple * associative containers are nested, then the tuple will be of the form * std::tuple. To avoid copies, and allow * editting of underlying values, the tuple contains references. * * @tparam Iterator The iterator type of the top-level collection. */ template class recursive_iterator : public detail::recursive_iterator_impl { public: using super = detail::recursive_iterator_impl; public: using super::super; recursive_iterator() = default; recursive_iterator & operator++() { (void)super::next(); return *this; } recursive_iterator operator++(int) { recursive_iterator tmp{*this}; (void)super::next(); return tmp; } bool operator!=(recursive_iterator const & other) const { return !(super::operator==(other)); } }; /** * @class recursive_iterator_n * @copydoc recursive_iterator * This object has bounded recursive depth, so that it can be used to get * sub-collections, which may be used in other functions. * * For Example: * @code * using map_type = std::map > >; * ... * recursive_iterator_n iter{ ... }; * std::vector & data = std::get<2>(*iter); * reload_data_from_file( std::get<1>(*iter), data ); * @endcode * * @tparam N The maximum depth to recurse into the object */ template class recursive_iterator_n : public detail::bounded_recursive_iterator_impl { public: using super = detail::bounded_recursive_iterator_impl; public: using super::super; recursive_iterator_n() = default; recursive_iterator_n & operator++() { (void)super::next(); return *this; } recursive_iterator_n operator++(int) { recursive_iterator_n tmp{*this}; (void)super::next(); return tmp; } bool operator!=(recursive_iterator_n const & other) const { return !(super::operator==(other)); } }; } namespace std { template auto get(::iterator::recursive_iterator const & iter) -> typename ::iterator::detail::accessor< I, ::iterator::recursive_iterator>::type { return iter; } template auto get(::iterator::recursive_iterator_n const & iter) -> typename ::iterator::detail::accessor< I, ::iterator::recursive_iterator_n>::type { static_assert(I < N, "Cannot get past bounding level"); return iter; } } template auto make_recursive_iterator(C & collect) -> iterator::recursive_iterator { return {make_end_aware_iterator(collect)}; } template auto make_recursive_iterator(C const & collect) -> iterator::recursive_iterator { return {make_end_aware_iterator(collect)}; } template auto make_recursive_iterator(C & collect) -> iterator::recursive_iterator_n { return {make_end_aware_iterator(collect)}; } template auto make_recursive_iterator(C const & collect) -> iterator::recursive_iterator_n { return {make_end_aware_iterator(collect)}; }