#pragma once #include #include #include #include namespace iterator { template class Facade { private: using self_type = CRTP; public: decltype(auto) operator*() const { return self().dereference(); } decltype(auto) operator->() const { if constexpr (std::is_reference{}) { return std::addressof(**this); } else { return detail::ArrowProxy{**this}; } } template requires(difference_type_arg && random_access) decltype(auto) operator[](D off) const { return *(self() + off); } self_type & operator++() { if constexpr (forward) { self().increment(); } else { static_assert(random_access, "requires .increment() or .advance()"); self() += 1; } return self(); } auto operator++(int) { if constexpr (single_pass) { ++*this; } else { auto tmp = self(); ++*this; return tmp; } } self_type & operator--() { if constexpr (bidirectional) { self().decrement(); } else { static_assert(random_access, "requires .decrement() or .advance()"); self() -= 1; } return self(); } self_type operator--(int) { auto tmp = self(); --*this; return tmp; } template requires(difference_type_arg && random_access) friend self_type & operator+=(self_type & self, D off) { self.advance(off); return self; } template requires(difference_type_arg && random_access) friend self_type & operator-=(self_type & self, D off) { self.advance(-off); return self; } template requires(difference_type_arg && random_access) friend auto operator+(self_type self, D off) { return self += off; } template requires(difference_type_arg && random_access) friend auto operator+(D off, self_type self) { return self += off; } template requires(difference_type_arg && random_access) friend auto operator-(self_type self, D off) { return self -= off; } friend auto operator-(self_type const & left, self_type const & right) requires(random_access) { return right.distance_to(left); } friend bool operator==(self_type const & left, self_type const & right) { if constexpr (has_sentinel) { return (left.at_end() && right.at_end()) || left.equal_to(right); } else { return left.equal_to(right); } } friend auto operator<=>(self_type const & left, self_type const & right) requires(random_access) { return (left - right) <=> 0; } protected: self_type & self() { return *static_cast(this); } self_type const & self() const { return *static_cast(this); } }; } template requires std::is_base_of_v, It> struct std::iterator_traits { static const It & _it; using reference = decltype(*_it); using pointer = decltype(_it.operator->()); using value_type = ::iterator::infer_value_type_t; using difference_type = ::iterator::infer_difference_type_t; using iterator_category = std::conditional_t< ::iterator::random_access, random_access_iterator_tag, std::conditional_t< ::iterator::bidirectional, bidirectional_iterator_tag, std::conditional_t<::iterator::single_pass, input_iterator_tag, forward_iterator_tag>>>; };