// // recursive_iterator.hpp // iterator // // Created by Sam Jaffe on 2/17/17. // #pragma once #include "iterator_fwd.hpp" namespace iterator { namespace detail { struct terminal_layer_tag_t; struct continue_layer_tag_t; template class recursive_iterator_base : public end_aware_iterator { private: using super = end_aware_iterator; protected: using recursive_category = terminal_layer_tag_t; public: using super::super; }; template class recursive_iterator_base::value_type::first_type>::value>::type> : public end_aware_iterator { private: 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: reference operator*() { auto & pair = super::operator*(); return std::tie(pair.first, pair.second); } using super::super; }; template class recursive_iterator_terminal : public recursive_iterator_base< Iterator > { private: using layer = recursive_iterator_base< Iterator >; public: recursive_iterator_terminal() = default; recursive_iterator_terminal(layer v) : layer(v) {} typename layer::reference operator*() { return layer::operator*(); } typename layer::pointer operator->() { return layer::operator->(); } protected: void next() { layer::operator++(); } void assign(layer eat) { static_cast(*this) = eat; } bool done() const { return layer::done(); } }; template class recursive_iterator_layer : public recursive_iterator_base< Iterator >, public RecursiveIterator_NextLayer { private: using next_layer = RecursiveIterator_NextLayer; using layer = recursive_iterator_base< Iterator >; protected: using recursive_category = continue_layer_tag_t; public: using value_type = typename next_layer::value_type; using reference = typename next_layer::reference; using pointer = typename next_layer::pointer; using difference_type = typename next_layer::difference_type; using iterator_category = typename next_layer::iterator_category; public: recursive_iterator_layer() = default; recursive_iterator_layer(layer v) : recursive_iterator_layer() { assign(v); } reference operator*() { return next_layer::operator*(); } pointer operator->() { return next_layer::operator->(); } bool operator==(recursive_iterator_layer const & other) const { return layer::operator==(other) && next_layer::operator==(other); } protected: void next() { layer & self = static_cast(*this); next_layer::next(); while ( next_layer::done() && !(++self).done() ) { next_layer::assign({ std::begin(*self), std::end(*self) }); } } void assign(layer v) { static_cast(*this) = v; if (!v.done()) { next_layer::assign({ std::begin(*v), std::end(*v) }); } } bool done() const { return layer::done(); } }; template struct next_layer_type { using type = std::tuple; }; template struct next_layer_type { using type = V; }; template class flatten_iterator_layer : recursive_iterator_base< Iterator >, RecursiveIterator_NextLayer { private: using next_layer = RecursiveIterator_NextLayer; using layer = recursive_iterator_base< Iterator >; using key_type = typename std::tuple_element<0, typename layer::value_type>::type; protected: using recursive_category = continue_layer_tag_t; using next_value_type = typename next_layer_type::type; using next_reference = typename next_layer_type::type; public: using value_type = decltype(std::tuple_cat(std::make_tuple(std::declval()), std::declval())); using reference = decltype(std::tuple_cat(std::tie(std::declval()), std::declval())); using pointer = void; using difference_type = typename next_layer::difference_type; using iterator_category = typename next_layer::iterator_category; public: flatten_iterator_layer() = default; flatten_iterator_layer(layer v) : flatten_iterator_layer() { assign(v); } reference operator*() { return std::tuple_cat(std::forward_as_tuple(std::get<0>(layer::operator*())), next_reference(next_layer::operator*())); } pointer operator->(); // pointer operator->() { // return next_layer::operator->(); // } bool operator==(flatten_iterator_layer const & other) const { return layer::operator==(other) && next_layer::operator==(other); } protected: void next() { layer & self = static_cast(*this); next_layer::next(); while ( next_layer::done() && !(++self).done() ) { next_layer::assign({ std::begin(self->second), std::end(self->second) }); } } void assign(layer v) { static_cast(*this) = v; if ( !v.done() ) { next_layer::assign({ std::begin(v->second), std::end(v->second) }); } } bool done() const { return layer::done(); } }; template class bounded_recursive_iterator_impl : public recursive_iterator_terminal< Iterator > { private: using super = recursive_iterator_terminal< Iterator >; public: using super::super; }; template class bounded_recursive_iterator_impl< Iterator, N, Max, typename std::enable_if>::type>::type > : public recursive_iterator_layer< Iterator , bounded_recursive_iterator_impl< value_iterator, N+1, Max > > { private: using next_layer = bounded_recursive_iterator_impl< value_iterator, N+1, Max >; using super = recursive_iterator_layer< Iterator, next_layer >; public: using super::super; }; template class recursive_iterator_impl : public recursive_iterator_terminal< Iterator > { private: using super = recursive_iterator_terminal< Iterator >; public: using super::super; }; template class recursive_iterator_impl< Iterator, typename void_t>::type > : public recursive_iterator_layer< Iterator, recursive_iterator_impl< value_iterator > > { private: using next_layer = recursive_iterator_impl< value_iterator >; using super = recursive_iterator_layer< Iterator, next_layer >; public: using super::super; }; template class bounded_recursive_iterator_impl< Iterator, N, Max, typename std::enable_if>::type>::type > : public flatten_iterator_layer< Iterator , bounded_recursive_iterator_impl< mapped_iterator, N+1, Max > > { private: using next_layer = bounded_recursive_iterator_impl< mapped_iterator, N+1, Max >; using super = flatten_iterator_layer< Iterator, next_layer >; public: using super::super; }; template class recursive_iterator_impl< Iterator, typename void_t>::type > : public flatten_iterator_layer< Iterator, recursive_iterator_impl< mapped_iterator > > { private: using next_layer = recursive_iterator_impl< mapped_iterator >; using super = flatten_iterator_layer< Iterator, next_layer >; public: using super::super; }; } template class recursive_iterator : public detail::recursive_iterator_impl< Iterator > { private: using super = detail::recursive_iterator_impl< Iterator >; public: using super::super; 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) { return !(super::operator==(other)); } }; template class recursive_iterator_n : public detail::bounded_recursive_iterator_impl< Iterator, 1, N > { private: using super = detail::bounded_recursive_iterator_impl< Iterator, 1, N >; public: using super::super; 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) { return !(super::operator==(other)); } }; } template auto make_recursive_iterator(C & collect) -> iterator::recursive_iterator { return {{ std::begin(collect), std::end(collect) }}; } template auto make_recursive_iterator(C const & collect) -> iterator::recursive_iterator { return {{ std::begin(collect), std::end(collect) }}; } template auto make_recursive_iterator(C & collect) -> iterator::recursive_iterator_n { return {{ std::begin(collect), std::end(collect) }}; } template auto make_recursive_iterator(C const & collect) -> iterator::recursive_iterator_n { return {{ std::begin(collect), std::end(collect) }}; }