join_iterator.hpp 2.4 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485
  1. //
  2. // join_iterator.hpp
  3. // iterator
  4. //
  5. // Created by Sam Jaffe on 2/7/17.
  6. //
  7. #pragma once
  8. #include "end_aware_iterator.hpp"
  9. #include <iterator>
  10. #include <utility>
  11. namespace iterator {
  12. template <typename MetaIterator> class joining_iterator {
  13. public:
  14. using join_iter = MetaIterator;
  15. using joinable_type = typename join_iter::value_type;
  16. using iter_type = decltype(std::begin(*std::declval<join_iter>()));
  17. using value_type = typename std::iterator_traits<iter_type>::value_type;
  18. using reference = typename std::iterator_traits<iter_type>::reference;
  19. using pointer = typename std::iterator_traits<iter_type>::pointer;
  20. using difference_type =
  21. typename std::iterator_traits<iter_type>::difference_type;
  22. using iterator_category = std::forward_iterator_tag;
  23. public:
  24. explicit joining_iterator() = default;
  25. template <typename I>
  26. joining_iterator(joining_iterator<I> const & other)
  27. : joiner_(other.join_iterator()), iterator_(other.element_iterator()) {}
  28. joining_iterator(end_aware_iterator<join_iter> join)
  29. : joining_iterator(join, {}, true) {}
  30. joining_iterator(end_aware_iterator<join_iter> join,
  31. end_aware_iterator<iter_type> elem, bool update = false)
  32. : joiner_(join), iterator_(elem) {
  33. if (update) { update_iterator(); }
  34. }
  35. joining_iterator & operator++() {
  36. if ((++iterator_).done()) {
  37. ++joiner_;
  38. update_iterator();
  39. }
  40. return *this;
  41. }
  42. joining_iterator operator++(int) {
  43. joining_iterator tmp{*this};
  44. operator++();
  45. return tmp;
  46. }
  47. reference operator*() const { return iterator_.operator*(); }
  48. pointer operator->() const { return iterator_.operator->(); }
  49. bool operator==(joining_iterator const & other) const {
  50. return joiner_ == other.joiner_ && iterator_ == other.iterator_;
  51. }
  52. bool operator!=(joining_iterator const & other) const {
  53. return !(operator==(other));
  54. }
  55. end_aware_iterator<join_iter> join_iterator() const { return joiner_; }
  56. end_aware_iterator<iter_type> element_iterator() const { return iterator_; }
  57. private:
  58. void update_iterator() {
  59. while (!joiner_.done() && std::begin(*joiner_) == std::end(*joiner_)) {
  60. ++joiner_;
  61. }
  62. if (!joiner_.done()) {
  63. iterator_ = {std::begin(*joiner_), std::end(*joiner_)};
  64. }
  65. }
  66. end_aware_iterator<join_iter> joiner_;
  67. end_aware_iterator<iter_type> iterator_;
  68. };
  69. }