join_iterator.hpp 3.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130
  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> class iterator {
  16. protected:
  17. using inner_t = decltype(*std::declval<Iter>());
  18. protected:
  19. iterator() = default;
  20. template <typename I>
  21. iterator(iterator<I> const & other)
  22. : iterator(other.join_iterator(), other.element_iterator()) {}
  23. template <typename C, typename = std::enable_if_t<detail::is_container_v<C>>>
  24. iterator(C && container)
  25. : iterator(end_aware_iterator(std::forward<C>(container))) {}
  26. iterator(end_aware_iterator<Iter> join) : iterator(join, {}, true) {}
  27. iterator(end_aware_iterator<Iter> join,
  28. end_aware_iterator<iter<inner_t>> elem, bool update = false)
  29. : joiner_(join), element_(elem) {
  30. if (update) { update_iterator(); }
  31. }
  32. void update_iterator() {
  33. while (!joiner_.at_end() &&
  34. (element_ = end_aware_iterator(*joiner_)).at_end()) {
  35. ++joiner_;
  36. }
  37. }
  38. protected:
  39. end_aware_iterator<Iter> joiner_;
  40. end_aware_iterator<iter<inner_t>> element_;
  41. };
  42. template <typename Iter>
  43. class iterator<Iter, std::enable_if_t<detail::is_rvalue_iterator_v<Iter>>> {
  44. protected:
  45. using inner_t = decltype(*std::declval<Iter>());
  46. protected:
  47. iterator() = default;
  48. template <typename C, typename = std::enable_if_t<detail::is_container_v<C>>>
  49. iterator(C && container) : joiner_(std::forward<C>(container)) {
  50. update_iterator();
  51. }
  52. iterator(end_aware_iterator<Iter> join) : joiner_(join) { update_iterator(); }
  53. void update_iterator() {
  54. while (!joiner_.at_end() && sync().at_end()) {
  55. ++joiner_;
  56. }
  57. }
  58. private:
  59. end_aware_iterator<iter<inner_t>> const & sync() {
  60. if (joiner_.at_end()) { return element_ = {}; }
  61. cache_ = std::make_shared<inner_t>(*joiner_);
  62. element_ = end_aware_iterator(*cache_);
  63. return element_;
  64. }
  65. protected:
  66. end_aware_iterator<Iter> joiner_;
  67. std::shared_ptr<inner_t> cache_;
  68. end_aware_iterator<iter<inner_t>> element_;
  69. };
  70. }
  71. namespace iterator {
  72. template <typename Iter>
  73. class joining_iterator : public facade<joining_iterator<Iter>>,
  74. public joining::iterator<Iter> {
  75. public:
  76. using super_t = joining::iterator<Iter>;
  77. struct sentinal_type {};
  78. static constexpr sentinal_type sentinal;
  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 at_end() const { return join_iterator().at_end(); }
  92. bool equal_to(joining_iterator const & other) const {
  93. return join_iterator() == other.join_iterator() &&
  94. element_iterator() == other.element_iterator();
  95. }
  96. auto const & join_iterator() const { return super_t::joiner_; }
  97. auto const & element_iterator() const { return super_t::element_; }
  98. };
  99. template <typename C> joining_iterator(C &&) -> joining_iterator<iter<C>>;
  100. template <typename JI>
  101. joining_iterator(end_aware_iterator<JI>) -> joining_iterator<JI>;
  102. }
  103. MAKE_ITERATOR_FACADE_TYPEDEFS_T(::iterator::joining_iterator);