end_aware_iterator.hpp 2.1 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374
  1. //
  2. // end_aware_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 <iterator>
  10. namespace iterator {
  11. template <typename Iterator>
  12. class end_aware_iterator {
  13. public:
  14. using iter_type = Iterator;
  15. using value_type = typename std::iterator_traits<iter_type>::value_type;
  16. using reference = typename std::iterator_traits<iter_type>::reference;
  17. using pointer = typename std::iterator_traits<iter_type>::pointer;
  18. using difference_type = typename std::iterator_traits<iter_type>::difference_type;
  19. using iterator_category = std::forward_iterator_tag;
  20. public:
  21. end_aware_iterator() = default;
  22. end_aware_iterator(iter_type it, iter_type end) : curr_(it), end_(end) {}
  23. end_aware_iterator(iter_type end) : curr_(end), end_(end) {}
  24. template <typename I>
  25. end_aware_iterator( end_aware_iterator<I> const & other )
  26. : curr_(other.current()), end_(other.end()) {
  27. }
  28. end_aware_iterator & operator++() {
  29. if ( !done() ) { ++curr_; }
  30. return *this;
  31. }
  32. end_aware_iterator operator++(int) {
  33. end_aware_iterator tmp{*this};
  34. operator++();
  35. return tmp;
  36. }
  37. reference operator*() { return *curr_; }
  38. pointer operator->() { return std::addressof(*curr_); }
  39. bool done() const { return curr_ == end_; }
  40. bool operator==(end_aware_iterator const & other) const {
  41. return (done() && other.done()) || (curr_ == other.curr_ && end_ == other.end_);
  42. }
  43. bool operator!=(end_aware_iterator const & other) {
  44. return !(operator==(other));
  45. }
  46. iter_type current() const { return curr_; }
  47. iter_type end() const { return end_; }
  48. private:
  49. iter_type curr_, end_;
  50. };
  51. }
  52. template <typename C>
  53. auto make_end_aware_iterator(C & collect) -> iterator::end_aware_iterator<decltype(std::begin(collect))> {
  54. return { std::begin(collect), std::end(collect) };
  55. }
  56. template <typename C>
  57. auto make_end_aware_iterator(C const & collect) -> iterator::end_aware_iterator<decltype(std::begin(collect))> {
  58. return { std::begin(collect), std::end(collect) };
  59. }