join_iterator.hpp 3.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129
  1. //
  2. // join_iterator.hpp
  3. // iterator
  4. //
  5. // Created by Sam Jaffe on 2/7/17.
  6. //
  7. #pragma once
  8. #include <iterator>
  9. #include <memory>
  10. #include <utility>
  11. #include <iterator/end_aware_iterator.hpp>
  12. #include <iterator/facade.h>
  13. #include <iterator/iterator_fwd.hpp>
  14. namespace iterator::joining {
  15. template <typename Iter, typename = void>
  16. class iterator {
  17. protected:
  18. using inner_t = decltype(*std::declval<Iter>());
  19. protected:
  20. iterator() = default;
  21. template <typename I>
  22. iterator(iterator<I> const & other)
  23. : iterator(other.join_iterator(), other.element_iterator()) {}
  24. template <typename C, typename = std::enable_if_t<detail::is_container_v<C>>>
  25. iterator(C && container)
  26. : iterator(end_aware_iterator(std::forward<C>(container))) {}
  27. iterator(end_aware_iterator<Iter> join) : iterator(join, {}, true) {}
  28. iterator(end_aware_iterator<Iter> join,
  29. end_aware_iterator<iter<inner_t>> elem, bool update = false)
  30. : joiner_(join), element_(elem) {
  31. if (update) { update_iterator(); }
  32. }
  33. void update_iterator() {
  34. while (!joiner_.at_end() &&
  35. (element_ = end_aware_iterator(*joiner_)).at_end()) {
  36. ++joiner_;
  37. }
  38. }
  39. protected:
  40. end_aware_iterator<Iter> joiner_;
  41. end_aware_iterator<iter<inner_t>> element_;
  42. };
  43. template <typename Iter>
  44. class iterator<Iter, std::enable_if_t<detail::is_rvalue_iterator_v<Iter>>> {
  45. protected:
  46. using inner_t = decltype(*std::declval<Iter>());
  47. protected:
  48. iterator() = default;
  49. template <typename C, typename = std::enable_if_t<detail::is_container_v<C>>>
  50. iterator(C && container) : joiner_(std::forward<C>(container)) {
  51. update_iterator();
  52. }
  53. iterator(end_aware_iterator<Iter> join) : joiner_(join) {
  54. update_iterator();
  55. }
  56. void update_iterator() {
  57. while (!joiner_.at_end() && sync().at_end()) {
  58. ++joiner_;
  59. }
  60. }
  61. private:
  62. end_aware_iterator<iter<inner_t>> const & sync() {
  63. if (joiner_.at_end()) { return element_ = {}; }
  64. cache_ = std::make_shared<inner_t>(*joiner_);
  65. element_ = end_aware_iterator(*cache_);
  66. return element_;
  67. }
  68. protected:
  69. end_aware_iterator<Iter> joiner_;
  70. std::shared_ptr<inner_t> cache_;
  71. end_aware_iterator<iter<inner_t>> element_;
  72. };
  73. }
  74. namespace iterator {
  75. template <typename Iter>
  76. class joining_iterator : public facade<joining_iterator<Iter>>, public joining::iterator<Iter> {
  77. public:
  78. using super_t = joining::iterator<Iter>;
  79. public:
  80. using super_t::super_t;
  81. template <typename C, typename = std::enable_if_t<detail::is_container_v<C>>>
  82. joining_iterator(C && container) : super_t(std::forward<C>(container)) {}
  83. joining_iterator(end_aware_iterator<Iter> join) : super_t(join) {}
  84. void increment() {
  85. if ((++super_t::element_).at_end()) {
  86. ++super_t::joiner_;
  87. super_t::update_iterator();
  88. }
  89. }
  90. decltype(auto) dereference() const { return *super_t::element_; }
  91. bool equal_to(joining_iterator const & other) const {
  92. return join_iterator() == other.join_iterator() &&
  93. element_iterator() == other.element_iterator();
  94. }
  95. auto const &join_iterator() const { return super_t::joiner_; }
  96. auto const &element_iterator() const { return super_t::element_; }
  97. };
  98. template <typename C> joining_iterator(C &&) -> joining_iterator<iter<C>>;
  99. template <typename JI>
  100. joining_iterator(end_aware_iterator<JI>) -> joining_iterator<JI>;
  101. }
  102. MAKE_ITERATOR_FACADE_TYPEDEFS_T(::iterator::joining_iterator);