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