indexed_iterator.h 1.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263
  1. //
  2. // indexed_iterator.h
  3. // iterator
  4. //
  5. // Created by Sam Jaffe on 3/5/17.
  6. //
  7. #pragma once
  8. #include <iterator>
  9. #include <iterator/facade.h>
  10. #include <iterator/forwards.h>
  11. #include <iterator/detail/macro.h>
  12. namespace iterator {
  13. template <typename It>
  14. class indexed_iterator : public facade<indexed_iterator<It>> {
  15. public:
  16. using reference =
  17. std::pair<size_t, typename std::iterator_traits<It>::reference>;
  18. using difference_type = typename std::iterator_traits<It>::difference_type;
  19. public:
  20. indexed_iterator() = default;
  21. indexed_iterator(It base) : base_(base) {}
  22. indexed_iterator(It base, size_t idx) : base_(base), index_(idx) {}
  23. template <typename O>
  24. indexed_iterator(indexed_iterator<O> const & oiter)
  25. : base_(oiter.base_), index_(oiter.index_) {}
  26. reference dereference() const { return {index_, *base_}; }
  27. void advance(difference_type off) {
  28. base_ += off;
  29. index_ += off;
  30. }
  31. // SFINAE means that if Iterator is not random access, then this still works
  32. // TODO: Investigate using _index for comparisons instead of _base
  33. bool equal_to(indexed_iterator const & other) const {
  34. return base_ == other.base_;
  35. }
  36. difference_type distance_to(indexed_iterator const & other) const {
  37. return other.base_ - base_;
  38. }
  39. SFINAE(detail::has_sentinel_type_v, bool) at_end() const {
  40. return base_ == typename It::sentinel_type();
  41. }
  42. private:
  43. template <typename O> friend class indexed_iterator;
  44. It base_;
  45. size_t index_{0};
  46. };
  47. template <typename It> indexed_iterator(It) -> indexed_iterator<It>;
  48. template <typename It> indexed_iterator(It, size_t) -> indexed_iterator<It>;
  49. }
  50. MAKE_ITERATOR_FACADE_TYPEDEFS_T(::iterator::indexed_iterator);