end_aware_iterator.h 1.8 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667
  1. //
  2. // end_aware_iterator.h
  3. // iterator
  4. //
  5. // Created by Sam Jaffe on 2/7/17.
  6. //
  7. #pragma once
  8. #include <iterator/detail/traits.h>
  9. #include <iterator/facade.h>
  10. #include <iterator/forwards.h>
  11. #include <iterator/sentinel.h>
  12. namespace iterator {
  13. /**
  14. * @class end_aware_iterator
  15. * @brief An iterator that keeps track of the relative end of the range.
  16. *
  17. * @tparam It The underlying iterator type
  18. */
  19. template <typename It>
  20. class end_aware_iterator : public facade<end_aware_iterator<It>> {
  21. public:
  22. using sentinel_type = sentinel_t;
  23. public:
  24. end_aware_iterator() = default;
  25. end_aware_iterator(It it, It end) : curr_(it), end_(end) {}
  26. template <typename C, typename = std::enable_if_t<detail::is_container_v<C>>>
  27. end_aware_iterator(C && container)
  28. : curr_(std::begin(container)), end_(std::end(container)) {
  29. static_assert(std::is_reference_v<C>,
  30. "Cannot access iterator of a temporary");
  31. }
  32. template <typename Ot>
  33. end_aware_iterator(end_aware_iterator<Ot> const & other)
  34. : curr_(other.curr_), end_(other.end_) {}
  35. end_aware_iterator(end_aware_iterator<It> other, end_aware_iterator<It>)
  36. : curr_(other.curr_), end_(other.end_) {}
  37. decltype(auto) dereference() const { return *curr_; }
  38. void increment() {
  39. if (!at_end()) { ++curr_; }
  40. }
  41. bool at_end() const { return curr_ == end_; }
  42. bool equal_to(end_aware_iterator const & other) const {
  43. return curr_ == other.curr_;
  44. }
  45. private:
  46. template <typename O> friend class end_aware_iterator;
  47. It curr_, end_;
  48. };
  49. template <typename C>
  50. end_aware_iterator(C &&) -> end_aware_iterator<detail::iter<C>>;
  51. template <typename It> end_aware_iterator(It, It) -> end_aware_iterator<It>;
  52. template <typename It>
  53. end_aware_iterator(end_aware_iterator<It>, end_aware_iterator<It>)
  54. -> end_aware_iterator<It>;
  55. }
  56. MAKE_ITERATOR_FACADE_TYPEDEFS_T(::iterator::end_aware_iterator);