join_iterator.hpp 2.5 KB

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