| 12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394 |
- //
- // join_iterator.h
- // iterator
- //
- // Created by Sam Jaffe on 2/7/17.
- //
- #pragma once
- #include <iterator>
- #include <iterator/capture_iterator.h>
- #include <iterator/end_aware_iterator.h>
- #include <iterator/facade.h>
- #include <iterator/forwards.h>
- namespace iterator {
- template <typename It> class JoinIterator : public Facade<JoinIterator<It>> {
- private:
- template <typename Ot> friend class JoinIterator;
- constexpr static bool requires_caching =
- !std::is_reference_v<std::iter_reference_t<It>>;
- public:
- using sentinel_type = sentinel_t;
- using outer_iterator_t =
- std::conditional_t<requires_caching,
- CaptureIterator<EndAwareIterator<It>>,
- EndAwareIterator<It>>;
- using inner_iterator_t =
- EndAwareIterator<iterator_t<std::iter_reference_t<outer_iterator_t>>>;
- private:
- outer_iterator_t outer_;
- inner_iterator_t inner_;
- public:
- JoinIterator() = default;
- template <typename Ot>
- JoinIterator(JoinIterator<Ot> const & other) : outer_(other.outer_) {
- safely_init_inner_iterator(other.outer_, other.inner_);
- }
- JoinIterator(Range auto & rng) : outer_(std::forward<decltype(rng)>(rng)) {
- update_iterator();
- }
- JoinIterator(outer_iterator_t outer) : outer_(outer) { update_iterator(); }
- JoinIterator(outer_iterator_t const & outer, inner_iterator_t const & inner)
- : outer_(outer) {
- safely_init_inner_iterator(outer, inner);
- }
- void increment() {
- if ((++inner_).at_end()) {
- ++outer_;
- update_iterator();
- }
- }
- decltype(auto) dereference() const { return *inner_; }
- bool at_end() const { return outer_.at_end(); }
- bool equal_to(JoinIterator const & other) const {
- return outer_ == other.outer_ && inner_ == other.inner_;
- }
- auto outer_iterator() const { return outer_; }
- auto inner_iterator() const { return inner_; }
- private:
- template <typename OuterIt, typename InnerIt>
- void safely_init_inner_iterator(OuterIt const & outer,
- InnerIt const & inner) {
- if constexpr (requires_caching) {
- inner_ = *outer_;
- std::advance(inner_, std::distance(InnerIt(*outer), inner));
- } else {
- inner_ = inner;
- }
- }
- void update_iterator() {
- while (!outer_.at_end() && (inner_ = *outer_).at_end()) {
- ++outer_;
- }
- }
- };
- template <typename C> JoinIterator(C &) -> JoinIterator<iterator_t<C>>;
- template <typename JI> JoinIterator(EndAwareIterator<JI>) -> JoinIterator<JI>;
- }
|