#pragma once #include #include #include "detail/arrow_proxy.h" #include "detail/traits.h" namespace iterator::detail { template struct has_equal_to : std::false_type {}; template struct has_equal_to : std::true_type {}; template struct has_distance_to : std::false_type {}; template struct has_distance_to : std::true_type {}; template struct is_advanceable_iterator : std::false_type {}; template struct is_advanceable_iterator : std::true_type {}; template struct is_single_pass_iterator : std::false_type {}; template struct is_single_pass_iterator> : std::true_type {}; template struct has_increment : std::false_type {}; template struct has_increment : std::true_type {}; template struct has_decrement : std::false_type {}; template struct has_decrement : std::true_type {}; template struct distance_to { using type = std::ptrdiff_t; }; template struct distance_to{}>> { using type = decltype(_val(T).distance_to(_val(T))); }; template struct sentinal_type { using type = void; }; template struct sentinal_type> { using type = typename T::sentinal_type; }; template using distance_to_t = typename distance_to::type; template using sentinal_type_t = typename sentinal_type::type; template constexpr bool has_equal_to_v = has_equal_to{}; template constexpr bool has_distance_to_v = has_distance_to{}; template constexpr bool has_increment_v = has_increment{}; template constexpr bool has_decrement_v = has_decrement{}; template constexpr bool is_advanceable_iterator_v = is_advanceable_iterator{}; template constexpr bool is_random_access_iterator_v = has_distance_to_v && is_advanceable_iterator_v; template constexpr bool is_bidirectional_iterator_v = has_decrement_v && has_increment_v && has_equal_to_v; template constexpr bool is_single_pass_iterator_v = is_single_pass_iterator{}; template using iterator_category_t = std::conditional_t< is_random_access_iterator_v, std::random_access_iterator_tag, std::conditional_t, std::bidirectional_iterator_tag, std::conditional_t, std::input_iterator_tag, std::forward_iterator_tag>>>; } #undef _val #undef exists namespace iterator { template using difference_type_arg_t = std::enable_if_t>>; template using sentinel_type_arg_t = std::enable_if_t>>; template class facade { public: decltype(auto) operator*() const { return self().dereference(); } decltype(auto) operator->() const { if constexpr (std::is_reference{}) { return std::addressof(**this); } else { return detail::arrow_proxy{**this}; } } template > decltype(auto) operator[](D off) const { return *(self() + off); } self_type & operator++() { if constexpr (detail::is_advanceable_iterator_v) { self() += 1; } else { self().increment(); } return self(); } auto operator++(int) { if constexpr (detail::is_single_pass_iterator_v) { ++*this; } else { auto tmp = self(); ++*this; return tmp; } } self_type & operator--() { if constexpr (detail::is_advanceable_iterator_v) { self() -= 1; } else { self().decrement(); } return self(); } self_type operator--(int) { auto tmp = self(); --*this; return tmp; } template > friend self_type & operator+=(self_type & self, D off) { static_assert(detail::is_advanceable_iterator_v, "must be advancable"); self.advance(off); return self; } template > friend self_type & operator-=(self_type & self, D off) { static_assert(detail::is_advanceable_iterator_v, "must be advancable"); self.advance(-off); return self; } template > friend auto operator+(self_type self, D off) { static_assert(detail::is_advanceable_iterator_v, "must be advancable"); return self += off; } template > friend auto operator+(D off, self_type self) { static_assert(detail::is_advanceable_iterator_v, "must be advancable"); return self += off; } template > friend auto operator-(self_type self, D off) { static_assert(detail::is_advanceable_iterator_v, "must be advancable"); return self -= off; } friend auto operator-(self_type const & left, self_type const & right) { return right.distance_to(left); } friend bool operator==(self_type const & left, self_type const & right) { if constexpr (detail::has_distance_to_v) { return (left - right) == 0; } else { return left.equal_to(right); } } template > friend auto operator==(self_type self, S) { return self.at_end(); } template > friend auto operator!=(self_type self, S) { return !self.at_end(); } friend bool operator!=(self_type const & left, self_type const & right) { return !(left == right); } friend bool operator<(self_type const & left, self_type const & right) { return (left - right) < 0; } friend bool operator<=(self_type const & left, self_type const & right) { return (left - right) <= 0; } friend bool operator>(self_type const & left, self_type const & right) { return (left - right) > 0; } friend bool operator>=(self_type const & left, self_type const & right) { return (left - right) >= 0; } private: self_type & self() { return *static_cast(this); } self_type const & self() const { return *static_cast(this); } }; } namespace std { // In C++20, a concept/requires could be used to eschew the need for the below // macros. template struct iterator_traits<::iterator::facade> { using reference = decltype(*std::declval()); using value_type = std::remove_cv_t>; using pointer = decltype(std::declval().operator->()); using difference_type = ::iterator::detail::distance_to_t; using iterator_category = ::iterator::detail::iterator_category_t; }; } #define MAKE_ITERATOR_FACADE_TYPEDEFS(type) \ namespace std { \ template <> \ struct iterator_traits \ : std::iterator_traits<::iterator::facade> {}; \ } #define MAKE_ITERATOR_FACADE_TYPEDEFS_T(type) \ namespace std { \ template \ struct iterator_traits> \ : std::iterator_traits<::iterator::facade>> {}; \ }