end_aware_iterator.hpp 1.7 KB

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