end_aware_iterator.h 2.0 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576
  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/forwards.h>
  10. #include <iterator/proxy.h>
  11. #include <iterator/sentinel.h>
  12. #include <iterator/detail/macro.h>
  13. namespace iterator {
  14. /**
  15. * @class end_aware_iterator
  16. * @brief An iterator that keeps track of the relative end of the range.
  17. *
  18. * @tparam It The underlying iterator type
  19. */
  20. template <typename It>
  21. class end_aware_iterator : public proxy<It, end_aware_iterator<It>> {
  22. public:
  23. using super_t = proxy<It, end_aware_iterator<It>>;
  24. using sentinel_type = sentinel_t;
  25. public:
  26. end_aware_iterator() = default;
  27. end_aware_iterator(It it, It end) : super_t(it), end_(end) {}
  28. template <typename C, REQUIRES(detail::is_container_v<C>)>
  29. end_aware_iterator(C && container)
  30. : super_t(std::begin(container)), end_(std::end(container)) {
  31. static_assert(std::is_reference_v<C>,
  32. "Cannot access iterator of a temporary");
  33. }
  34. template <typename Ot>
  35. end_aware_iterator(end_aware_iterator<Ot> const & other)
  36. : super_t(other.impl()), end_(other.end_) {}
  37. bool at_end() const {
  38. if constexpr (super_t::category_enum == category::random_access) {
  39. return super_t::impl() >= end_;
  40. } else {
  41. return super_t::impl() == end_;
  42. }
  43. }
  44. SFINAE(super_t::category_enum == category::random_access)
  45. friend auto operator-(sentinel_type, end_aware_iterator const &self) {
  46. return self.end() - self.impl();
  47. }
  48. protected:
  49. It end() const { return end_; }
  50. private:
  51. template <typename O> friend class end_aware_iterator;
  52. It end_;
  53. };
  54. template <typename C>
  55. end_aware_iterator(C &&) -> end_aware_iterator<detail::iter<C>>;
  56. template <typename It> end_aware_iterator(It, It) -> end_aware_iterator<It>;
  57. template <typename It>
  58. end_aware_iterator(end_aware_iterator<It>, end_aware_iterator<It>)
  59. -> end_aware_iterator<It>;
  60. }
  61. MAKE_ITERATOR_FACADE_TYPEDEFS_T(::iterator::end_aware_iterator);
  62. #include <iterator/detail/undef.h>