join_iterator.hpp 3.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132
  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. public:
  19. iterator() = default;
  20. template <typename I>
  21. iterator(iterator<I> const & other)
  22. : iterator(other.joiner_, other.element_) {}
  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. protected:
  33. void update_iterator() {
  34. while (!joiner_.at_end() &&
  35. (element_ = end_aware_iterator(*joiner_)).at_end()) {
  36. ++joiner_;
  37. }
  38. }
  39. protected:
  40. template <typename, typename> friend class iterator;
  41. end_aware_iterator<Iter> joiner_;
  42. end_aware_iterator<iter<inner_t>> element_;
  43. };
  44. template <typename Iter>
  45. class iterator<Iter, std::enable_if_t<detail::is_rvalue_iterator_v<Iter>>> {
  46. protected:
  47. using inner_t = decltype(*std::declval<Iter>());
  48. public:
  49. iterator() = default;
  50. template <typename C, typename = std::enable_if_t<detail::is_container_v<C>>>
  51. iterator(C && container) : joiner_(std::forward<C>(container)) {
  52. update_iterator();
  53. }
  54. iterator(end_aware_iterator<Iter> join) : joiner_(join) { update_iterator(); }
  55. protected:
  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>>,
  77. public joining::iterator<Iter> {
  78. public:
  79. using super_t = joining::iterator<Iter>;
  80. using sentinel_type = sentinel_t;
  81. public:
  82. using super_t::super_t;
  83. template <typename C, typename = std::enable_if_t<detail::is_container_v<C>>>
  84. joining_iterator(C && container) : super_t(std::forward<C>(container)) {}
  85. joining_iterator(end_aware_iterator<Iter> join) : super_t(join) {}
  86. void increment() {
  87. if ((++super_t::element_).at_end()) {
  88. ++super_t::joiner_;
  89. super_t::update_iterator();
  90. }
  91. }
  92. decltype(auto) dereference() const { return *super_t::element_; }
  93. bool at_end() const { return join_iterator().at_end(); }
  94. bool equal_to(joining_iterator const & other) const {
  95. return join_iterator() == other.join_iterator() &&
  96. element_iterator() == other.element_iterator();
  97. }
  98. auto const & join_iterator() const { return super_t::joiner_; }
  99. auto const & element_iterator() const { return super_t::element_; }
  100. };
  101. template <typename C> joining_iterator(C &&) -> joining_iterator<iter<C>>;
  102. template <typename JI>
  103. joining_iterator(end_aware_iterator<JI>) -> joining_iterator<JI>;
  104. }
  105. MAKE_ITERATOR_FACADE_TYPEDEFS_T(::iterator::joining_iterator);