facade.h 3.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148
  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. if constexpr (has_sentinel<self_type>) {
  94. return (left.at_end() && right.at_end()) || left.equal_to(right);
  95. } else {
  96. return left.equal_to(right);
  97. }
  98. }
  99. friend auto operator<=>(self_type const & left, self_type const & right)
  100. requires(random_access<self_type>)
  101. {
  102. return (left - right) <=> 0;
  103. }
  104. protected:
  105. self_type & self() { return *static_cast<self_type *>(this); }
  106. self_type const & self() const {
  107. return *static_cast<self_type const *>(this);
  108. }
  109. };
  110. }
  111. template <typename It>
  112. requires std::is_base_of_v<iterator::facade<It>, It>
  113. struct std::iterator_traits<It> {
  114. static const It & _it;
  115. using reference = decltype(*_it);
  116. using pointer = decltype(_it.operator->());
  117. using value_type = ::iterator::infer_value_type_t<It>;
  118. using difference_type = ::iterator::infer_difference_type_t<It>;
  119. using iterator_category = std::conditional_t<
  120. ::iterator::random_access<It>, random_access_iterator_tag,
  121. std::conditional_t<
  122. ::iterator::bidirectional<It>, bidirectional_iterator_tag,
  123. std::conditional_t<::iterator::single_pass<It>, input_iterator_tag,
  124. forward_iterator_tag>>>;
  125. };
  126. #include <iterator/detail/undef.h>