// // join_iterator.hpp // iterator // // Created by Sam Jaffe on 2/7/17. // #pragma once #include "end_aware_iterator.hpp" #include #include #include "facade.h" namespace iterator { template class joining_iterator : public facade> { public: using join_iter = MetaIterator; using joinable_type = typename join_iter::value_type; using iter_type = decltype(std::begin(*std::declval())); 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(); } } void increment() { if ((iterator_++).at_end()) { ++joiner_; update_iterator(); } } decltype(auto) dereference() const { return *iterator_; } bool equal_to(joining_iterator const & other) const { return joiner_ == other.joiner_ && iterator_ == other.iterator_; } end_aware_iterator join_iterator() const { return joiner_; } end_aware_iterator element_iterator() const { return iterator_; } private: void update_iterator() { while (!joiner_.at_end() && make_end_aware_iterator(*joiner_).at_end()) { ++joiner_; } if (!joiner_.at_end()) { iterator_ = make_end_aware_iterator(*joiner_); } } end_aware_iterator joiner_; end_aware_iterator iterator_; }; template joining_iterator(end_aware_iterator) -> joining_iterator; template joining_iterator(end_aware_iterator, end_aware_iterator) -> joining_iterator; } MAKE_ITERATOR_FACADE_TYPEDEFS_T(::iterator::joining_iterator);