join_iterator.hpp 2.4 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182
  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. #include "facade.h"
  12. namespace iterator {
  13. template <typename MetaIterator>
  14. class joining_iterator : public facade<joining_iterator<MetaIterator>> {
  15. public:
  16. using join_iter = MetaIterator;
  17. using joinable_type = typename join_iter::value_type;
  18. using iter_type = decltype(std::begin(*std::declval<join_iter>()));
  19. using value_type = typename std::iterator_traits<iter_type>::value_type;
  20. using reference = typename std::iterator_traits<iter_type>::reference;
  21. using pointer = typename std::iterator_traits<iter_type>::pointer;
  22. using difference_type =
  23. typename std::iterator_traits<iter_type>::difference_type;
  24. using iterator_category = std::forward_iterator_tag;
  25. public:
  26. explicit joining_iterator() = default;
  27. template <typename I>
  28. joining_iterator(joining_iterator<I> const & other)
  29. : joiner_(other.join_iterator()), iterator_(other.element_iterator()) {}
  30. joining_iterator(end_aware_iterator<join_iter> join)
  31. : joining_iterator(join, {}, true) {}
  32. joining_iterator(end_aware_iterator<join_iter> join,
  33. end_aware_iterator<iter_type> elem, bool update = false)
  34. : joiner_(join), iterator_(elem) {
  35. if (update) { update_iterator(); }
  36. }
  37. void increment() {
  38. if ((iterator_++).at_end()) {
  39. ++joiner_;
  40. update_iterator();
  41. }
  42. }
  43. decltype(auto) dereference() const { return *iterator_; }
  44. bool equal_to(joining_iterator const & other) const {
  45. return joiner_ == other.joiner_ && iterator_ == other.iterator_;
  46. }
  47. end_aware_iterator<join_iter> join_iterator() const { return joiner_; }
  48. end_aware_iterator<iter_type> element_iterator() const { return iterator_; }
  49. private:
  50. void update_iterator() {
  51. while (!joiner_.at_end() && make_end_aware_iterator(*joiner_).at_end()) {
  52. ++joiner_;
  53. }
  54. if (!joiner_.at_end()) { iterator_ = make_end_aware_iterator(*joiner_); }
  55. }
  56. end_aware_iterator<join_iter> joiner_;
  57. end_aware_iterator<iter_type> iterator_;
  58. };
  59. template <typename JI>
  60. joining_iterator(end_aware_iterator<JI>) -> joining_iterator<JI>;
  61. template <typename JI, typename IT>
  62. joining_iterator(end_aware_iterator<JI>, end_aware_iterator<IT>)
  63. -> joining_iterator<JI>;
  64. }
  65. MAKE_ITERATOR_FACADE_TYPEDEFS_T(::iterator::joining_iterator);