|
|
@@ -11,119 +11,91 @@
|
|
|
#include <memory>
|
|
|
#include <utility>
|
|
|
|
|
|
+#include <iterator/capture_iterator.h>
|
|
|
#include <iterator/end_aware_iterator.h>
|
|
|
#include <iterator/facade.h>
|
|
|
#include <iterator/forwards.h>
|
|
|
|
|
|
#include <iterator/detail/macro.h>
|
|
|
|
|
|
-namespace iterator::joining {
|
|
|
-template <typename Iter, typename = void> class iterator {
|
|
|
-protected:
|
|
|
- using inner_t = DEREF_TYPE(Iter);
|
|
|
+namespace iterator {
|
|
|
+template <typename It>
|
|
|
+class joining_iterator : public facade<joining_iterator<It>> {
|
|
|
+private:
|
|
|
+ template <typename Ot> friend class joining_iterator;
|
|
|
+ constexpr static bool requires_caching = detail::is_rvalue_iterator_v<It>;
|
|
|
|
|
|
public:
|
|
|
- iterator() = default;
|
|
|
-
|
|
|
- template <typename I>
|
|
|
- iterator(iterator<I> const & other)
|
|
|
- : iterator(other.joiner_, other.element_) {}
|
|
|
-
|
|
|
- template <typename C, typename = std::enable_if_t<detail::is_container_v<C>>>
|
|
|
- iterator(C && container)
|
|
|
- : iterator(end_aware_iterator(std::forward<C>(container))) {}
|
|
|
+ using sentinel_type = sentinel_t;
|
|
|
+ using outer_iterator_t =
|
|
|
+ std::conditional_t<requires_caching,
|
|
|
+ capture_iterator<end_aware_iterator<It>>,
|
|
|
+ end_aware_iterator<It>>;
|
|
|
+ using inner_iterator_t =
|
|
|
+ end_aware_iterator<detail::iter<DEREF_TYPE(outer_iterator_t)>>;
|
|
|
|
|
|
- iterator(end_aware_iterator<Iter> join) : iterator(join, {}, true) {}
|
|
|
+private:
|
|
|
+ outer_iterator_t outer_;
|
|
|
+ inner_iterator_t inner_;
|
|
|
|
|
|
- iterator(end_aware_iterator<Iter> join,
|
|
|
- end_aware_iterator<detail::iter<inner_t>> elem, bool update = false)
|
|
|
- : joiner_(join), element_(elem) {
|
|
|
- if (update) { update_iterator(); }
|
|
|
- }
|
|
|
+public:
|
|
|
+ joining_iterator() = default;
|
|
|
|
|
|
-protected:
|
|
|
- void update_iterator() {
|
|
|
- while (!joiner_.at_end() &&
|
|
|
- (element_ = end_aware_iterator(*joiner_)).at_end()) {
|
|
|
- ++joiner_;
|
|
|
- }
|
|
|
+ template <typename Ot>
|
|
|
+ joining_iterator(joining_iterator<Ot> const & other) : outer_(other.outer_) {
|
|
|
+ safely_init_inner_iterator(other.outer_, other.inner_);
|
|
|
}
|
|
|
|
|
|
-protected:
|
|
|
- template <typename, typename> friend class iterator;
|
|
|
- end_aware_iterator<Iter> joiner_;
|
|
|
- end_aware_iterator<detail::iter<inner_t>> element_;
|
|
|
-};
|
|
|
-
|
|
|
-template <typename Iter>
|
|
|
-class iterator<Iter, std::enable_if_t<detail::is_rvalue_iterator_v<Iter>>> {
|
|
|
-protected:
|
|
|
- using inner_t = DEREF_TYPE(Iter);
|
|
|
-
|
|
|
-public:
|
|
|
- iterator() = default;
|
|
|
template <typename C, typename = std::enable_if_t<detail::is_container_v<C>>>
|
|
|
- iterator(C && container) : joiner_(std::forward<C>(container)) {
|
|
|
+ joining_iterator(C && container) : outer_(std::forward<C>(container)) {
|
|
|
update_iterator();
|
|
|
}
|
|
|
|
|
|
- iterator(end_aware_iterator<Iter> join) : joiner_(join) { update_iterator(); }
|
|
|
-
|
|
|
-protected:
|
|
|
- void update_iterator() {
|
|
|
- while (!joiner_.at_end() && sync().at_end()) {
|
|
|
- ++joiner_;
|
|
|
- }
|
|
|
+ joining_iterator(outer_iterator_t outer) : outer_(outer) {
|
|
|
+ update_iterator();
|
|
|
}
|
|
|
|
|
|
-private:
|
|
|
- end_aware_iterator<detail::iter<inner_t>> const & sync() {
|
|
|
- if (joiner_.at_end()) { return element_ = {}; }
|
|
|
- cache_ = std::make_shared<inner_t>(*joiner_);
|
|
|
- element_ = end_aware_iterator(*cache_);
|
|
|
- return element_;
|
|
|
+ joining_iterator(outer_iterator_t const & outer,
|
|
|
+ inner_iterator_t const & inner)
|
|
|
+ : outer_(outer) {
|
|
|
+ safely_init_inner_iterator(outer, inner);
|
|
|
}
|
|
|
|
|
|
-protected:
|
|
|
- end_aware_iterator<Iter> joiner_;
|
|
|
- std::shared_ptr<inner_t> cache_;
|
|
|
- end_aware_iterator<detail::iter<inner_t>> element_;
|
|
|
-};
|
|
|
-}
|
|
|
-
|
|
|
-namespace iterator {
|
|
|
-template <typename Iter>
|
|
|
-class joining_iterator : public facade<joining_iterator<Iter>>,
|
|
|
- public joining::iterator<Iter> {
|
|
|
-public:
|
|
|
- using super_t = joining::iterator<Iter>;
|
|
|
- using sentinel_type = sentinel_t;
|
|
|
-
|
|
|
-public:
|
|
|
- using super_t::super_t;
|
|
|
-
|
|
|
- template <typename C, typename = std::enable_if_t<detail::is_container_v<C>>>
|
|
|
- joining_iterator(C && container) : super_t(std::forward<C>(container)) {}
|
|
|
-
|
|
|
- joining_iterator(end_aware_iterator<Iter> join) : super_t(join) {}
|
|
|
-
|
|
|
void increment() {
|
|
|
- if ((++super_t::element_).at_end()) {
|
|
|
- ++super_t::joiner_;
|
|
|
- super_t::update_iterator();
|
|
|
+ if ((++inner_).at_end()) {
|
|
|
+ ++outer_;
|
|
|
+ update_iterator();
|
|
|
}
|
|
|
}
|
|
|
|
|
|
- decltype(auto) dereference() const { return *super_t::element_; }
|
|
|
+ decltype(auto) dereference() const { return *inner_; }
|
|
|
|
|
|
- bool at_end() const { return join_iterator().at_end(); }
|
|
|
+ bool at_end() const { return outer_iterator().at_end(); }
|
|
|
bool equal_to(joining_iterator const & other) const {
|
|
|
- return join_iterator() == other.join_iterator() &&
|
|
|
- element_iterator() == other.element_iterator();
|
|
|
+ return outer_iterator() == other.outer_iterator() &&
|
|
|
+ inner_iterator() == other.inner_iterator();
|
|
|
+ }
|
|
|
+
|
|
|
+ auto const & outer_iterator() const { return outer_; }
|
|
|
+ auto const & 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;
|
|
|
+ }
|
|
|
}
|
|
|
|
|
|
- auto const & join_iterator() const { return super_t::joiner_; }
|
|
|
- auto const & element_iterator() const { return super_t::element_; }
|
|
|
+ void update_iterator() {
|
|
|
+ while (!outer_.at_end() && (inner_ = *outer_).at_end()) {
|
|
|
+ ++outer_;
|
|
|
+ }
|
|
|
+ }
|
|
|
};
|
|
|
|
|
|
template <typename C>
|