end_aware_iterator.h 1.8 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374
  1. //
  2. // end_aware_iterator.h
  3. // iterator
  4. //
  5. // Created by Sam Jaffe on 2/7/17.
  6. //
  7. #pragma once
  8. #include <ranges>
  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 EndAwareIterator
  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 EndAwareIterator : public Proxy<It, EndAwareIterator<It>> {
  22. public:
  23. using super_t = Proxy<It, EndAwareIterator<It>>;
  24. using sentinel_type = sentinel_t;
  25. public:
  26. EndAwareIterator() = default;
  27. EndAwareIterator(It it, It end) : super_t(it), end_(end) {}
  28. EndAwareIterator(Range auto & container)
  29. : super_t(std::begin(container)), end_(std::end(container)) {}
  30. template <typename Ot>
  31. EndAwareIterator(EndAwareIterator<Ot> const & other)
  32. : super_t(other.impl()), end_(other.end_) {}
  33. operator std::ranges::subrange<It>() const {
  34. return {super_t::impl(), end()};
  35. }
  36. bool at_end() const {
  37. if constexpr (std::random_access_iterator<It>) {
  38. return super_t::impl() >= end_;
  39. } else {
  40. return super_t::impl() == end_;
  41. }
  42. }
  43. friend auto operator-(sentinel_type, EndAwareIterator const & self)
  44. requires(std::random_access_iterator<It>)
  45. {
  46. return self.end() - self.impl();
  47. }
  48. protected:
  49. It end() const { return end_; }
  50. private:
  51. template <typename O> friend class EndAwareIterator;
  52. It end_;
  53. };
  54. template <typename C> EndAwareIterator(C &&) -> EndAwareIterator<iterator_t<C>>;
  55. template <typename It> EndAwareIterator(It, It) -> EndAwareIterator<It>;
  56. template <typename It>
  57. EndAwareIterator(EndAwareIterator<It>, EndAwareIterator<It>)
  58. -> EndAwareIterator<It>;
  59. }
  60. #include <iterator/detail/undef.h>