indexed_iterator.hpp 1.5 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758
  1. //
  2. // indexed_iterator.hpp
  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/iterator_fwd.hpp>
  11. namespace iterator {
  12. template <typename It>
  13. class indexed_iterator : public facade<indexed_iterator<It>> {
  14. public:
  15. using reference =
  16. std::pair<size_t, typename std::iterator_traits<It>::reference>;
  17. using difference_type = typename std::iterator_traits<It>::difference_type;
  18. public:
  19. indexed_iterator() = default;
  20. indexed_iterator(It base) : base_(base) {}
  21. indexed_iterator(It base, size_t idx) : base_(base), index_(idx) {}
  22. template <typename O>
  23. indexed_iterator(indexed_iterator<O> const & oiter)
  24. : base_(oiter.base_), index_(oiter.index_) {}
  25. reference dereference() const { return {index_, *base_}; }
  26. void advance(difference_type off) {
  27. base_ += off;
  28. index_ += off;
  29. }
  30. // SFINAE means that if Iterator is not random access, then this still works
  31. // TODO: Investigate using _index for comparisons instead of _base
  32. bool equal_to(indexed_iterator const & other) const {
  33. return base_ == other.base_;
  34. }
  35. difference_type distance_to(indexed_iterator const & other) const {
  36. return other.base_ - base_;
  37. }
  38. private:
  39. template <typename O> friend class indexed_iterator;
  40. It base_;
  41. size_t index_{0};
  42. };
  43. template <typename It> indexed_iterator(It) -> indexed_iterator<It>;
  44. template <typename It> indexed_iterator(It, size_t) -> indexed_iterator<It>;
  45. }
  46. MAKE_ITERATOR_FACADE_TYPEDEFS_T(::iterator::indexed_iterator);