facade.h 3.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147
  1. #pragma once
  2. #include <iterator>
  3. #include <type_traits>
  4. #include <iterator/concepts.h>
  5. #include <iterator/detail/arrow_proxy.h>
  6. #include <iterator/detail/macro.h>
  7. namespace iterator {
  8. template <typename CRTP> class Facade {
  9. private:
  10. using self_type = CRTP;
  11. public:
  12. decltype(auto) operator*() const { return self().dereference(); }
  13. decltype(auto) operator->() const {
  14. if constexpr (std::is_reference<decltype(**this)>{}) {
  15. return std::addressof(**this);
  16. } else {
  17. return detail::ArrowProxy{**this};
  18. }
  19. }
  20. template <typename D>
  21. requires(difference_type_arg<D, self_type> && random_access<self_type>)
  22. decltype(auto) operator[](D off) const {
  23. return *(self() + off);
  24. }
  25. self_type & operator++() {
  26. if constexpr (forward<self_type>) {
  27. self().increment();
  28. } else {
  29. static_assert(random_access<self_type>,
  30. "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>,
  49. "requires .decrement() or .advance()");
  50. self() -= 1;
  51. }
  52. return self();
  53. }
  54. self_type operator--(int) {
  55. auto tmp = self();
  56. --*this;
  57. return tmp;
  58. }
  59. template <typename D>
  60. requires(difference_type_arg<D, self_type> && random_access<self_type>)
  61. friend self_type & operator+=(self_type & self, D off) {
  62. self.advance(off);
  63. return self;
  64. }
  65. template <typename D>
  66. requires(difference_type_arg<D, self_type> && random_access<self_type>)
  67. friend self_type & operator-=(self_type & self, D off) {
  68. self.advance(-off);
  69. return self;
  70. }
  71. template <typename D>
  72. requires(difference_type_arg<D, self_type> && random_access<self_type>)
  73. friend auto operator+(self_type self, D off) {
  74. return self += off;
  75. }
  76. template <typename D>
  77. requires(difference_type_arg<D, self_type> && random_access<self_type>)
  78. friend auto operator+(D off, self_type self) {
  79. return self += off;
  80. }
  81. template <typename D>
  82. requires(difference_type_arg<D, self_type> && random_access<self_type>)
  83. friend auto operator-(self_type self, D off) {
  84. return self -= off;
  85. }
  86. friend auto operator-(self_type const & left, self_type const & right)
  87. requires(random_access<self_type>)
  88. {
  89. return right.distance_to(left);
  90. }
  91. friend bool operator==(self_type const & left, self_type const & right) {
  92. if constexpr (has_sentinel<self_type>) {
  93. return (left.at_end() && right.at_end()) || left.equal_to(right);
  94. } else {
  95. return left.equal_to(right);
  96. }
  97. }
  98. friend auto operator<=>(self_type const & left, self_type const & right)
  99. requires(random_access<self_type>)
  100. {
  101. return (left - right) <=> 0;
  102. }
  103. protected:
  104. self_type & self() { return *static_cast<self_type *>(this); }
  105. self_type const & self() const {
  106. return *static_cast<self_type const *>(this);
  107. }
  108. };
  109. }
  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. #include <iterator/detail/undef.h>