// // join_iterator.hpp // iterator // // Created by Sam Jaffe on 2/7/17. // #pragma once #include "iterator_fwd.hpp" #include "end_aware_iterator.hpp" #include namespace iterator { template class joining_iterator { public: using join_iter = MetaIterator; using joinable_type = typename join_iter::value_type; using iter_type = detail::value_iterator; using value_type = typename std::iterator_traits::value_type; using reference = typename std::iterator_traits::reference; using pointer = typename std::iterator_traits::pointer; using difference_type = typename std::iterator_traits::difference_type; using iterator_category = std::forward_iterator_tag; public: explicit joining_iterator( ) = default; template joining_iterator( joining_iterator const & other ) : joiner_(other.join_iterator()), iterator_(other.element_iterator()) { } joining_iterator( end_aware_iterator join ) : joining_iterator(join, {}, true) {} joining_iterator( end_aware_iterator join, end_aware_iterator elem, bool update = false ) : joiner_(join), iterator_(elem) { if ( update ) { update_iterator(); } } joining_iterator & operator++() { if ( (++iterator_).done() ) { ++joiner_; update_iterator(); } return *this; } joining_iterator operator++(int) { joining_iterator tmp{*this}; operator++(); return tmp; } reference operator*() const { return iterator_.operator*(); } pointer operator->() const { return iterator_.operator->(); } bool operator==(joining_iterator const & other) const { return joiner_ == other.joiner_ && iterator_ == other.iterator_; } bool operator!=(joining_iterator const & other) { return !(operator==(other)); } end_aware_iterator join_iterator() const { return joiner_; } end_aware_iterator element_iterator() const { return iterator_; } private: void update_iterator() { while ( !joiner_.done() && std::begin(*joiner_) == std::end(*joiner_) ) { ++joiner_; } if ( !joiner_.done() ) { iterator_ = { std::begin(*joiner_), std::end(*joiner_) }; } } end_aware_iterator joiner_; end_aware_iterator iterator_; }; }