join_iterator.h 3.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137
  1. //
  2. // join_iterator.h
  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.h>
  12. #include <iterator/facade.h>
  13. #include <iterator/forwards.h>
  14. #include <iterator/detail/macro.h>
  15. namespace iterator::joining {
  16. template <typename Iter, typename = void> class iterator {
  17. protected:
  18. using inner_t = DEREF_TYPE(Iter);
  19. public:
  20. iterator() = default;
  21. template <typename I>
  22. iterator(iterator<I> const & other)
  23. : iterator(other.joiner_, other.element_) {}
  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<detail::iter<inner_t>> elem, bool update = false)
  30. : joiner_(join), element_(elem) {
  31. if (update) { update_iterator(); }
  32. }
  33. protected:
  34. void update_iterator() {
  35. while (!joiner_.at_end() &&
  36. (element_ = end_aware_iterator(*joiner_)).at_end()) {
  37. ++joiner_;
  38. }
  39. }
  40. protected:
  41. template <typename, typename> friend class iterator;
  42. end_aware_iterator<Iter> joiner_;
  43. end_aware_iterator<detail::iter<inner_t>> element_;
  44. };
  45. template <typename Iter>
  46. class iterator<Iter, std::enable_if_t<detail::is_rvalue_iterator_v<Iter>>> {
  47. protected:
  48. using inner_t = DEREF_TYPE(Iter);
  49. public:
  50. iterator() = default;
  51. template <typename C, typename = std::enable_if_t<detail::is_container_v<C>>>
  52. iterator(C && container) : joiner_(std::forward<C>(container)) {
  53. update_iterator();
  54. }
  55. iterator(end_aware_iterator<Iter> join) : joiner_(join) { update_iterator(); }
  56. protected:
  57. void update_iterator() {
  58. while (!joiner_.at_end() && sync().at_end()) {
  59. ++joiner_;
  60. }
  61. }
  62. private:
  63. end_aware_iterator<detail::iter<inner_t>> const & sync() {
  64. if (joiner_.at_end()) { return element_ = {}; }
  65. cache_ = std::make_shared<inner_t>(*joiner_);
  66. element_ = end_aware_iterator(*cache_);
  67. return element_;
  68. }
  69. protected:
  70. end_aware_iterator<Iter> joiner_;
  71. std::shared_ptr<inner_t> cache_;
  72. end_aware_iterator<detail::iter<inner_t>> element_;
  73. };
  74. }
  75. namespace iterator {
  76. template <typename Iter>
  77. class joining_iterator : public facade<joining_iterator<Iter>>,
  78. public joining::iterator<Iter> {
  79. public:
  80. using super_t = joining::iterator<Iter>;
  81. using sentinel_type = sentinel_t;
  82. public:
  83. using super_t::super_t;
  84. template <typename C, typename = std::enable_if_t<detail::is_container_v<C>>>
  85. joining_iterator(C && container) : super_t(std::forward<C>(container)) {}
  86. joining_iterator(end_aware_iterator<Iter> join) : super_t(join) {}
  87. void increment() {
  88. if ((++super_t::element_).at_end()) {
  89. ++super_t::joiner_;
  90. super_t::update_iterator();
  91. }
  92. }
  93. decltype(auto) dereference() const { return *super_t::element_; }
  94. bool at_end() const { return join_iterator().at_end(); }
  95. bool equal_to(joining_iterator const & other) const {
  96. return join_iterator() == other.join_iterator() &&
  97. element_iterator() == other.element_iterator();
  98. }
  99. auto const & join_iterator() const { return super_t::joiner_; }
  100. auto const & element_iterator() const { return super_t::element_; }
  101. };
  102. template <typename C>
  103. joining_iterator(C &&) -> joining_iterator<detail::iter<C>>;
  104. template <typename JI>
  105. joining_iterator(end_aware_iterator<JI>) -> joining_iterator<JI>;
  106. }
  107. MAKE_ITERATOR_FACADE_TYPEDEFS_T(::iterator::joining_iterator);
  108. #include <iterator/detail/undef.h>