|
|
@@ -6,82 +6,33 @@
|
|
|
#include <iterator/detail/arrow_proxy.h>
|
|
|
#include <iterator/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, std::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 {};
|
|
|
+#include <iterator/detail/macro.h>
|
|
|
|
|
|
+namespace iterator::detail {
|
|
|
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)));
|
|
|
+struct distance_to<T, EXISTS(VAL(T).distance_to(VAL(T)))> {
|
|
|
+ using type = decltype(VAL(T).distance_to(VAL(T)));
|
|
|
};
|
|
|
|
|
|
template <typename T> using distance_to_t = typename distance_to<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
|
|
|
-
|
|
|
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 self_type> class facade {
|
|
|
+template <typename CRTP, category C> class facade {
|
|
|
+private:
|
|
|
+ using self_type = CRTP;
|
|
|
+
|
|
|
+public:
|
|
|
+ constexpr static auto category_enum = C;
|
|
|
+
|
|
|
public:
|
|
|
decltype(auto) operator*() const { return self().dereference(); }
|
|
|
|
|
|
@@ -93,13 +44,14 @@ public:
|
|
|
}
|
|
|
}
|
|
|
|
|
|
- template <typename D, typename = difference_type_arg_t<D, self_type>>
|
|
|
+ template <typename D, typename = difference_type_arg_t<D, self_type>,
|
|
|
+ REQUIRES(DEFER(D) && C == category::random_access)>
|
|
|
decltype(auto) operator[](D off) const {
|
|
|
return *(self() + off);
|
|
|
}
|
|
|
|
|
|
self_type & operator++() {
|
|
|
- if constexpr (detail::is_advanceable_iterator_v<self_type>) {
|
|
|
+ if constexpr (C == category::random_access) {
|
|
|
self() += 1;
|
|
|
} else {
|
|
|
self().increment();
|
|
|
@@ -108,7 +60,7 @@ public:
|
|
|
}
|
|
|
|
|
|
auto operator++(int) {
|
|
|
- if constexpr (detail::is_single_pass_iterator_v<self_type>) {
|
|
|
+ if constexpr (C == category::single_pass) {
|
|
|
++*this;
|
|
|
} else {
|
|
|
auto tmp = self();
|
|
|
@@ -117,8 +69,9 @@ public:
|
|
|
}
|
|
|
}
|
|
|
|
|
|
+ SFINAE(C >= category::bidirectional)
|
|
|
self_type & operator--() {
|
|
|
- if constexpr (detail::is_advanceable_iterator_v<self_type>) {
|
|
|
+ if constexpr (C == category::random_access) {
|
|
|
self() -= 1;
|
|
|
} else {
|
|
|
self().decrement();
|
|
|
@@ -126,55 +79,52 @@ public:
|
|
|
return self();
|
|
|
}
|
|
|
|
|
|
+ SFINAE(C >= category::bidirectional)
|
|
|
self_type operator--(int) {
|
|
|
auto tmp = self();
|
|
|
--*this;
|
|
|
return tmp;
|
|
|
}
|
|
|
|
|
|
- template <typename D, typename = difference_type_arg_t<D, self_type>>
|
|
|
+ template <typename D, typename = difference_type_arg_t<D, self_type>,
|
|
|
+ REQUIRES(DEFER(D) && C == category::random_access)>
|
|
|
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>>
|
|
|
+ template <typename D, typename = difference_type_arg_t<D, self_type>,
|
|
|
+ REQUIRES(DEFER(D) && C == category::random_access)>
|
|
|
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>>
|
|
|
+ template <typename D, typename = difference_type_arg_t<D, self_type>,
|
|
|
+ REQUIRES(DEFER(D) && C == category::random_access)>
|
|
|
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>>
|
|
|
+ template <typename D, typename = difference_type_arg_t<D, self_type>,
|
|
|
+ REQUIRES(DEFER(D) && C == category::random_access)>
|
|
|
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>>
|
|
|
+ template <typename D, typename = difference_type_arg_t<D, self_type>,
|
|
|
+ REQUIRES(DEFER(D) && C == category::random_access)>
|
|
|
friend auto operator-(self_type self, D off) {
|
|
|
- static_assert(detail::is_advanceable_iterator_v<self_type>,
|
|
|
- "must be advancable");
|
|
|
return self -= off;
|
|
|
}
|
|
|
|
|
|
+ SFINAE(C == category::random_access)
|
|
|
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>) {
|
|
|
+ if constexpr (C == category::random_access) {
|
|
|
return (left - right) == 0;
|
|
|
} else {
|
|
|
return left.equal_to(right);
|
|
|
@@ -185,23 +135,27 @@ public:
|
|
|
return !(left == right);
|
|
|
}
|
|
|
|
|
|
+ SFINAE(C == category::random_access)
|
|
|
friend bool operator<(self_type const & left, self_type const & right) {
|
|
|
return (left - right) < 0;
|
|
|
}
|
|
|
|
|
|
+ SFINAE(C == category::random_access)
|
|
|
friend bool operator<=(self_type const & left, self_type const & right) {
|
|
|
return (left - right) <= 0;
|
|
|
}
|
|
|
|
|
|
+ SFINAE(C == category::random_access)
|
|
|
friend bool operator>(self_type const & left, self_type const & right) {
|
|
|
return (left - right) > 0;
|
|
|
}
|
|
|
|
|
|
+ SFINAE(C == category::random_access)
|
|
|
friend bool operator>=(self_type const & left, self_type const & right) {
|
|
|
return (left - right) >= 0;
|
|
|
}
|
|
|
|
|
|
-private:
|
|
|
+protected:
|
|
|
self_type & self() { return *static_cast<self_type *>(this); }
|
|
|
self_type const & self() const {
|
|
|
return *static_cast<self_type const *>(this);
|
|
|
@@ -211,20 +165,14 @@ private:
|
|
|
|
|
|
// In C++20, a concept/requires could be used to eschew the need for the below
|
|
|
// macros.
|
|
|
-template <typename I> struct std::iterator_traits<::iterator::facade<I>> {
|
|
|
- using reference = decltype(*std::declval<I>());
|
|
|
- using value_type = std::remove_cv_t<std::remove_reference_t<reference>>;
|
|
|
- using pointer = decltype(std::declval<I>().operator->());
|
|
|
- using difference_type = ::iterator::detail::distance_to_t<I>;
|
|
|
- using iterator_category = ::iterator::detail::iterator_category_t<I>;
|
|
|
-};
|
|
|
-
|
|
|
-#define MAKE_ITERATOR_FACADE_TYPEDEFS(type) \
|
|
|
- template <> \
|
|
|
- struct std::iterator_traits<type> \
|
|
|
- : std::iterator_traits<::iterator::facade<type>> {}
|
|
|
+#define MAKE_ITERATOR_FACADE_TYPEDEFS_T(Iter) \
|
|
|
+ template <typename... T> struct std::iterator_traits<Iter<T...>> { \
|
|
|
+ using type = Iter<T...>; \
|
|
|
+ using reference = decltype(*std::declval<type>()); \
|
|
|
+ using value_type = std::decay_t<reference>; \
|
|
|
+ using pointer = decltype(std::declval<type>().operator->()); \
|
|
|
+ using difference_type = ::iterator::detail::distance_to_t<type>; \
|
|
|
+ using iterator_category = ::iterator::detail::tag_for_t<type>; \
|
|
|
+ }
|
|
|
|
|
|
-#define MAKE_ITERATOR_FACADE_TYPEDEFS_T(type) \
|
|
|
- template <typename... T> \
|
|
|
- struct std::iterator_traits<type<T...>> \
|
|
|
- : std::iterator_traits<::iterator::facade<type<T...>>> {}
|
|
|
+#include <iterator/detail/undef.h>
|