facade.h 5.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184
  1. #pragma once
  2. #include <concepts>
  3. #include <iterator>
  4. #include <type_traits>
  5. #include <iterator/concepts.h>
  6. #include <iterator/detail/arrow_proxy.h>
  7. #include <iterator/detail/macro.h>
  8. namespace iterator {
  9. template <typename CRTP> class facade {
  10. private:
  11. using self_type = CRTP;
  12. public:
  13. decltype(auto) operator*() const { return self().dereference(); }
  14. decltype(auto) operator->() const {
  15. if constexpr (std::is_reference<decltype(**this)>{}) {
  16. return std::addressof(**this);
  17. } else {
  18. return detail::arrow_proxy{**this};
  19. }
  20. }
  21. template <typename D>
  22. requires(difference_type_arg<D, self_type> && random_access<self_type>)
  23. decltype(auto) operator[](D off) const {
  24. return *(self() + off);
  25. }
  26. self_type & operator++() {
  27. if constexpr (forward<self_type>) {
  28. self().increment();
  29. } else {
  30. static_assert(random_access<self_type>,
  31. "requires .increment() or .advance()");
  32. self() += 1;
  33. }
  34. return self();
  35. }
  36. auto operator++(int) {
  37. if constexpr (single_pass<self_type>) {
  38. ++*this;
  39. } else {
  40. auto tmp = self();
  41. ++*this;
  42. return tmp;
  43. }
  44. }
  45. self_type & operator--() {
  46. if constexpr (bidirectional<self_type>) {
  47. self().decrement();
  48. } else {
  49. static_assert(random_access<self_type>,
  50. "requires .decrement() or .advance()");
  51. self() -= 1;
  52. }
  53. return self();
  54. }
  55. self_type operator--(int) {
  56. auto tmp = self();
  57. --*this;
  58. return tmp;
  59. }
  60. template <typename D>
  61. requires(difference_type_arg<D, self_type> && random_access<self_type>)
  62. friend self_type & operator+=(self_type & self, D off) {
  63. self.advance(off);
  64. return self;
  65. }
  66. template <typename D>
  67. requires(difference_type_arg<D, self_type> && random_access<self_type>)
  68. friend self_type & operator-=(self_type & self, D off) {
  69. self.advance(-off);
  70. return self;
  71. }
  72. template <typename D>
  73. requires(difference_type_arg<D, self_type> && random_access<self_type>)
  74. friend auto operator+(self_type self, D off) {
  75. return self += off;
  76. }
  77. template <typename D>
  78. requires(difference_type_arg<D, self_type> && random_access<self_type>)
  79. friend auto operator+(D off, self_type self) {
  80. return self += off;
  81. }
  82. template <typename D>
  83. requires(difference_type_arg<D, self_type> && random_access<self_type>)
  84. friend auto operator-(self_type self, D off) {
  85. return self -= off;
  86. }
  87. friend auto operator-(self_type const & left, self_type const & right)
  88. requires(random_access<self_type>)
  89. {
  90. return right.distance_to(left);
  91. }
  92. friend bool operator==(self_type const & left, self_type const & right) {
  93. return left.equal_to(right);
  94. }
  95. friend auto operator<=>(self_type const & left, self_type const & right)
  96. requires(random_access<self_type>)
  97. {
  98. return (left - right) <=> 0;
  99. }
  100. protected:
  101. self_type & self() { return *static_cast<self_type *>(this); }
  102. self_type const & self() const {
  103. return *static_cast<self_type const *>(this);
  104. }
  105. };
  106. }
  107. // In C++20, a concept/requires could be used to eschew the need for the below
  108. // macros.
  109. #define MAKE_ITERATOR_FACADE_TYPEDEFS_T(Iter)
  110. template <typename It>
  111. requires std::is_base_of_v<iterator::facade<It>, It>
  112. struct std::iterator_traits<It> {
  113. static const It & _it;
  114. using reference = decltype(*_it);
  115. using pointer = decltype(_it.operator->());
  116. using value_type = ::iterator::infer_value_type_t<It>;
  117. using difference_type = ::iterator::infer_difference_type_t<It>;
  118. using iterator_category = std::conditional_t<
  119. ::iterator::random_access<It>, random_access_iterator_tag,
  120. std::conditional_t<
  121. ::iterator::bidirectional<It>, bidirectional_iterator_tag,
  122. std::conditional_t<::iterator::single_pass<It>, input_iterator_tag,
  123. forward_iterator_tag>>>;
  124. };
  125. // template <typename It> requires(std::derived_from<It, iterator::facade<It,
  126. // iterator::category::single_pass>>) struct std::iterator_traits<It> {
  127. // using reference = decltype(std::declval<It>().operator*());
  128. // using value_type = std::decay_t<reference>;
  129. // using pointer = decltype(std::declval<It>().operator->());
  130. // using difference_type = ::iterator::infer_difference_type_t<It>;
  131. // using iterator_category = std::input_iterator_tag;
  132. // };
  133. //
  134. // template <typename It> requires(std::derived_from<It, iterator::facade<It,
  135. // iterator::category::forward>>) struct std::iterator_traits<It> {
  136. // using reference = decltype(std::declval<It>().operator*());
  137. // using value_type = std::decay_t<reference>;
  138. // using pointer = decltype(std::declval<It>().operator->());
  139. // using difference_type = ::iterator::infer_difference_type_t<It>;
  140. // using iterator_category = std::forward_iterator_tag;
  141. // };
  142. //
  143. // template <typename It> requires(std::derived_from<It, iterator::facade<It,
  144. // iterator::category::bidirectional>>) struct std::iterator_traits<It> {
  145. // using reference = decltype(std::declval<It>().operator*());
  146. // using value_type = std::decay_t<reference>;
  147. // using pointer = decltype(std::declval<It>().operator->());
  148. // using difference_type = ::iterator::infer_difference_type_t<It>;
  149. // using iterator_category = std::bidirectional_iterator_tag;
  150. // };
  151. //
  152. // template <typename It> requires(std::derived_from<It, iterator::facade<It,
  153. // iterator::category::random_access>>) struct std::iterator_traits<It> {
  154. // using reference = decltype(std::declval<It>().operator*());
  155. // using value_type = std::decay_t<reference>;
  156. // using pointer = decltype(std::declval<It>().operator->());
  157. // using difference_type = ::iterator::infer_difference_type_t<It>;
  158. // using iterator_category = std::random_access_iterator_tag;
  159. // };
  160. #include <iterator/detail/undef.h>