indexed_iterator.h 2.0 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879
  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
  15. : public facade<indexed_iterator<It>, detail::category_for_v<It>> {
  16. public:
  17. using reference = std::pair<size_t, DEREF_TYPE(It)>;
  18. using difference_type = typename std::iterator_traits<It>::difference_type;
  19. private:
  20. using super_t = facade<indexed_iterator<It>, detail::category_for_v<It>>;
  21. public:
  22. indexed_iterator() = default;
  23. indexed_iterator(It base) : base_(base) {}
  24. indexed_iterator(It base, size_t idx) : base_(base), index_(idx) {}
  25. template <typename O>
  26. indexed_iterator(indexed_iterator<O> const & oiter)
  27. : base_(oiter.base_), index_(oiter.index_) {}
  28. reference dereference() const { return {index_, *base_}; }
  29. SFINAE(super_t::category_enum >= category::forward) void decrement() {
  30. ++base_;
  31. ++index_;
  32. }
  33. SFINAE(super_t::category_enum >= category::bidirectional) void increment() {
  34. --base_;
  35. --index_;
  36. }
  37. SFINAE(super_t::category_enum >= category::random_access)
  38. void advance(difference_type off) {
  39. base_ += off;
  40. index_ += off;
  41. }
  42. SFINAE(super_t::category_enum < category::random_access)
  43. bool equal_to(indexed_iterator const & other) const {
  44. return base_ == other.base_;
  45. }
  46. SFINAE(super_t::category_enum >= category::random_access)
  47. difference_type distance_to(indexed_iterator const & other) const {
  48. return other.base_ - base_;
  49. }
  50. SFINAE(detail::has_sentinel_type_v<It>) bool at_end() const {
  51. return base_ == typename It::sentinel_type();
  52. }
  53. private:
  54. template <typename O> friend class indexed_iterator;
  55. It base_;
  56. size_t index_{0};
  57. };
  58. template <typename It> indexed_iterator(It) -> indexed_iterator<It>;
  59. template <typename It> indexed_iterator(It, size_t) -> indexed_iterator<It>;
  60. }
  61. MAKE_ITERATOR_FACADE_TYPEDEFS_T(::iterator::indexed_iterator);