end_aware_iterator.hpp 1.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869
  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 "facade.h"
  10. namespace iterator {
  11. /**
  12. * @class end_aware_iterator
  13. * @brief An iterator that keeps track of the relative end of the range.
  14. *
  15. * @tparam It The underlying iterator type
  16. */
  17. template <typename It>
  18. class end_aware_iterator : public facade<end_aware_iterator<It>> {
  19. public:
  20. using value_type = typename It::value_type;
  21. struct sentinel_type {};
  22. static constexpr sentinel_type sentinel;
  23. public:
  24. end_aware_iterator() = default;
  25. end_aware_iterator(It it, It end) : curr_(it), end_(end) {}
  26. end_aware_iterator(It end) : curr_(end), end_(end) {}
  27. template <typename I>
  28. end_aware_iterator(end_aware_iterator<I> const & other)
  29. : curr_(other.current()), end_(other.end()) {}
  30. decltype(auto) dereference() const { return *curr_; }
  31. void increment() { ++curr_; }
  32. bool at_end() const { return curr_ == end_; }
  33. bool equal_to(end_aware_iterator const & other) const {
  34. // TODO: Fix this clause
  35. return (at_end() && other.at_end()) || curr_ == other.curr_;
  36. }
  37. It current() const { return curr_; }
  38. It end() const { return end_; }
  39. private:
  40. It curr_, end_;
  41. };
  42. template <typename It> end_aware_iterator(It) -> end_aware_iterator<It>;
  43. template <typename It> end_aware_iterator(It, It) -> end_aware_iterator<It>;
  44. }
  45. MAKE_ITERATOR_FACADE_TYPEDEFS_T(::iterator::end_aware_iterator);
  46. template <typename Iter>
  47. iterator::end_aware_iterator<Iter> make_end_aware_iterator(Iter a, Iter b) {
  48. return iterator::end_aware_iterator<Iter>(a, b);
  49. }
  50. template <typename C> auto make_end_aware_iterator(C & collect) {
  51. return make_end_aware_iterator(std::begin(collect), std::end(collect));
  52. }
  53. template <typename C> auto make_end_aware_iterator(C const & collect) {
  54. return make_end_aware_iterator(std::begin(collect), std::end(collect));
  55. }