facade.h 3.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143
  1. #pragma once
  2. #include <iterator>
  3. #include <type_traits>
  4. #include <iterator/concepts.h>
  5. #include <iterator/detail/arrow_proxy.h>
  6. namespace iterator {
  7. template <typename CRTP> class Facade {
  8. private:
  9. using self_type = CRTP;
  10. public:
  11. decltype(auto) operator*() const { return self().dereference(); }
  12. decltype(auto) operator->() const {
  13. if constexpr (std::is_reference<decltype(**this)>{}) {
  14. return std::addressof(**this);
  15. } else {
  16. return detail::ArrowProxy{**this};
  17. }
  18. }
  19. template <typename D>
  20. requires(difference_type_arg<D, self_type> && random_access<self_type>)
  21. decltype(auto) operator[](D off) const {
  22. return *(self() + off);
  23. }
  24. self_type & operator++() {
  25. if constexpr (forward<self_type>) {
  26. self().increment();
  27. } else {
  28. static_assert(random_access<self_type>,
  29. "requires .increment() or .advance()");
  30. self() += 1;
  31. }
  32. return self();
  33. }
  34. auto operator++(int) {
  35. if constexpr (single_pass<self_type>) {
  36. ++*this;
  37. } else {
  38. auto tmp = self();
  39. ++*this;
  40. return tmp;
  41. }
  42. }
  43. self_type & operator--() {
  44. if constexpr (bidirectional<self_type>) {
  45. self().decrement();
  46. } else {
  47. static_assert(random_access<self_type>,
  48. "requires .decrement() or .advance()");
  49. self() -= 1;
  50. }
  51. return self();
  52. }
  53. self_type operator--(int) {
  54. auto tmp = self();
  55. --*this;
  56. return tmp;
  57. }
  58. template <typename D>
  59. requires(difference_type_arg<D, self_type> && random_access<self_type>)
  60. friend self_type & operator+=(self_type & self, D off) {
  61. self.advance(off);
  62. return self;
  63. }
  64. template <typename D>
  65. requires(difference_type_arg<D, self_type> && random_access<self_type>)
  66. friend self_type & operator-=(self_type & self, D off) {
  67. self.advance(-off);
  68. return self;
  69. }
  70. template <typename D>
  71. requires(difference_type_arg<D, self_type> && random_access<self_type>)
  72. friend auto operator+(self_type self, D off) {
  73. return self += off;
  74. }
  75. template <typename D>
  76. requires(difference_type_arg<D, self_type> && random_access<self_type>)
  77. friend auto operator+(D off, self_type self) {
  78. return self += off;
  79. }
  80. template <typename D>
  81. requires(difference_type_arg<D, self_type> && random_access<self_type>)
  82. friend auto operator-(self_type self, D off) {
  83. return self -= off;
  84. }
  85. friend auto operator-(self_type const & left, self_type const & right)
  86. requires(random_access<self_type>)
  87. {
  88. return right.distance_to(left);
  89. }
  90. friend bool operator==(self_type const & left, self_type const & right) {
  91. if constexpr (has_sentinel<self_type>) {
  92. return (left.at_end() && right.at_end()) || left.equal_to(right);
  93. } else {
  94. return left.equal_to(right);
  95. }
  96. }
  97. friend auto operator<=>(self_type const & left, self_type const & right)
  98. requires(random_access<self_type>)
  99. {
  100. return (left - right) <=> 0;
  101. }
  102. protected:
  103. self_type & self() { return *static_cast<self_type *>(this); }
  104. self_type const & self() const {
  105. return *static_cast<self_type const *>(this);
  106. }
  107. };
  108. }
  109. template <typename It>
  110. requires std::is_base_of_v<iterator::Facade<It>, It>
  111. struct std::iterator_traits<It> {
  112. static const It & _it;
  113. using reference = decltype(*_it);
  114. using pointer = decltype(_it.operator->());
  115. using value_type = ::iterator::infer_value_type_t<It>;
  116. using difference_type = ::iterator::infer_difference_type_t<It>;
  117. using iterator_category = std::conditional_t<
  118. ::iterator::random_access<It>, random_access_iterator_tag,
  119. std::conditional_t<
  120. ::iterator::bidirectional<It>, bidirectional_iterator_tag,
  121. std::conditional_t<::iterator::single_pass<It>, input_iterator_tag,
  122. forward_iterator_tag>>>;
  123. };