facade.h 5.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180
  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> requires (difference_type_arg<D, self_type> &&
  22. 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>, "requires .increment() or .advance()");
  31. self() += 1;
  32. }
  33. return self();
  34. }
  35. auto operator++(int) {
  36. if constexpr (single_pass<self_type>) {
  37. ++*this;
  38. } else {
  39. auto tmp = self();
  40. ++*this;
  41. return tmp;
  42. }
  43. }
  44. self_type & operator--() {
  45. if constexpr (bidirectional<self_type>) {
  46. self().decrement();
  47. } else {
  48. static_assert(random_access<self_type>, "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> requires (difference_type_arg<D, self_type> &&
  59. 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> requires (difference_type_arg<D, self_type> &&
  65. 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> requires (difference_type_arg<D, self_type> &&
  71. random_access<self_type>)
  72. friend auto operator+(self_type self, D off) {
  73. return self += off;
  74. }
  75. template <typename D> requires (difference_type_arg<D, self_type> &&
  76. random_access<self_type>)
  77. friend auto operator+(D off, self_type self) {
  78. return self += off;
  79. }
  80. template <typename D> requires (difference_type_arg<D, self_type> &&
  81. 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) requires(random_access<self_type>) {
  86. return right.distance_to(left);
  87. }
  88. friend bool operator==(self_type const & left, self_type const & right) {
  89. return left.equal_to(right);
  90. }
  91. friend auto operator<=>(self_type const & left, self_type const & right) requires(random_access<self_type>) {
  92. return (left - right) <=> 0;
  93. }
  94. protected:
  95. self_type & self() { return *static_cast<self_type *>(this); }
  96. self_type const & self() const {
  97. return *static_cast<self_type const *>(this);
  98. }
  99. };
  100. }
  101. // In C++20, a concept/requires could be used to eschew the need for the below
  102. // macros.
  103. #define MAKE_ITERATOR_FACADE_TYPEDEFS_T(Iter)
  104. template <typename It> requires std::is_base_of_v<iterator::facade<It>, It>
  105. struct std::iterator_traits<It> {
  106. static const It& _it;
  107. using reference = decltype(*_it);
  108. using pointer = decltype(_it.operator->());
  109. using value_type = ::iterator::infer_value_type_t<It>;
  110. using difference_type = ::iterator::infer_difference_type_t<It>;
  111. using iterator_category = std::conditional_t<
  112. ::iterator::random_access<It>,
  113. random_access_iterator_tag,
  114. std::conditional_t<
  115. ::iterator::bidirectional<It>,
  116. bidirectional_iterator_tag,
  117. std::conditional_t<::iterator::single_pass<It>, input_iterator_tag, forward_iterator_tag>
  118. >
  119. >;
  120. };
  121. //template <typename It> requires(std::derived_from<It, iterator::facade<It, iterator::category::single_pass>>)
  122. //struct std::iterator_traits<It> {
  123. // using reference = decltype(std::declval<It>().operator*());
  124. // using value_type = std::decay_t<reference>;
  125. // using pointer = decltype(std::declval<It>().operator->());
  126. // using difference_type = ::iterator::infer_difference_type_t<It>;
  127. // using iterator_category = std::input_iterator_tag;
  128. //};
  129. //
  130. //template <typename It> requires(std::derived_from<It, iterator::facade<It, iterator::category::forward>>)
  131. //struct std::iterator_traits<It> {
  132. // using reference = decltype(std::declval<It>().operator*());
  133. // using value_type = std::decay_t<reference>;
  134. // using pointer = decltype(std::declval<It>().operator->());
  135. // using difference_type = ::iterator::infer_difference_type_t<It>;
  136. // using iterator_category = std::forward_iterator_tag;
  137. //};
  138. //
  139. //template <typename It> requires(std::derived_from<It, iterator::facade<It, iterator::category::bidirectional>>)
  140. //struct std::iterator_traits<It> {
  141. // using reference = decltype(std::declval<It>().operator*());
  142. // using value_type = std::decay_t<reference>;
  143. // using pointer = decltype(std::declval<It>().operator->());
  144. // using difference_type = ::iterator::infer_difference_type_t<It>;
  145. // using iterator_category = std::bidirectional_iterator_tag;
  146. //};
  147. //
  148. //template <typename It> requires(std::derived_from<It, iterator::facade<It, iterator::category::random_access>>)
  149. //struct std::iterator_traits<It> {
  150. // using reference = decltype(std::declval<It>().operator*());
  151. // using value_type = std::decay_t<reference>;
  152. // using pointer = decltype(std::declval<It>().operator->());
  153. // using difference_type = ::iterator::infer_difference_type_t<It>;
  154. // using iterator_category = std::random_access_iterator_tag;
  155. //};
  156. #include <iterator/detail/undef.h>