Explorar o código

refactor: eliminate traits.h in favor of concepts

Sam Jaffe hai 2 meses
pai
achega
c4e5388a3d

+ 26 - 1
include/iterator/concepts.h

@@ -9,6 +9,8 @@
 #pragma once
 
 #include <concepts>
+#include <ranges>
+#include <string_view>
 
 namespace iterator {
 template <typename It>
@@ -51,7 +53,13 @@ template <typename T, typename U> concept not_same_as = not std::same_as<T, U>;
 
 template <typename It>
 concept has_sentinel = requires(It const &it) {
-  { it.as_end() } -> std::same_as<bool>;
+  typename It::sentinel_type;
+  { it.at_end() } -> std::same_as<bool>;
+};
+
+template <typename It, typename S>
+concept sentinel_for = has_sentinel<It> && requires(It const &it, S s) {
+  { s - it } -> std::integral;
 };
 
 template <typename It>
@@ -75,4 +83,21 @@ concept random_access = requires(It &it, infer_difference_type_t<It> offset) {
   { it.equal_to(it) } -> std::same_as<bool>;
   { it.advance(offset) } -> std::same_as<void>;
 };
+
+template <typename C> concept Char = std::same_as<C, char> || std::same_as<C, wchar_t> || std::same_as<C, char16_t> || std::same_as<C, char32_t> || std::same_as<C, char8_t>;
+
+template <typename S> concept LegacyString = requires(S const &t) {
+  { t.c_str() };
+};
+
+template <typename S> concept StringViewCompat = Char<typename S::value_type> && requires(S const &t) {
+  { std::basic_string_view{t} };
+};
+
+template <typename S> concept String = LegacyString<S> || StringViewCompat<S>;
+
+template <typename C>
+concept Range = (not String<C>) && std::ranges::range<C>;
+template <typename C>
+using iterator_t = decltype(std::begin(std::declval<C&>()));
 }

+ 5 - 39
include/iterator/detail/recursive_traits.h

@@ -1,8 +1,6 @@
 #pragma once
 
-#include <iterator>
-
-#include <iterator/detail/traits.h>
+#include <iterator/concepts.h>
 
 namespace iterator::recursive {
 // Type deduction guides for constructing recursive iterators.
@@ -11,41 +9,9 @@ enum class recursion_type { END, THRU, ASSOC };
 // Helpers for condensing type deductions
 template <typename It> using value = decltype(std::begin(*std::declval<It>()));
 
-template <typename It>
-using mapped = decltype(std::begin(std::declval<It>()->second));
-
-template <typename It> using key_type = decltype(std::declval<It>()->first);
-
-// Type trait to identify value_type ~~ std::pair<K const, V>, which is
-// a safe bet towards 'this is an associative container type'
-template <typename T, typename = void>
-struct is_associative : std::false_type {};
-template <typename T>
-struct is_associative<T, std::enable_if_t<std::is_const_v<key_type<T>>>>
-    : std::true_type {};
-
-template <typename T, typename = void> struct typeclass_t {
-  static constexpr recursion_type const value{recursion_type::END};
-};
-
-template <typename T> struct is_string_iter : std::false_type {};
-template <> struct is_string_iter<std::string::iterator> : std::true_type {};
-template <>
-struct is_string_iter<std::string::const_iterator> : std::true_type {};
-
-template <typename T> constexpr bool is_string_iter_v = is_string_iter<T>{};
-
-template <typename T>
-struct typeclass_t<T, std::enable_if_t<!is_string_iter_v<value<T>>>> {
-  constexpr static recursion_type value{recursion_type::THRU};
-};
-
-template <typename T>
-struct typeclass_t<T, std::enable_if_t<is_string_iter_v<value<T>>>> {
-  constexpr static recursion_type value{recursion_type::END};
-};
+template <typename V> concept associative_value = std::is_const_v<typename V::first_type>;
+template <typename V> concept recursive_associative = associative_value<V> && Range<typename V::second_type>;
 
-template <typename T> struct typeclass_t<T, std::void_t<mapped<T>>> {
-  constexpr static recursion_type value{recursion_type::ASSOC};
-};
+template <typename V> constexpr auto typeclass = recursive_associative<V> ? recursion_type::ASSOC : (Range<V> ? recursion_type::THRU : recursion_type::END);
+template <typename It> constexpr auto iter_typeclass = typeclass<std::iter_value_t<It>>;
 }

+ 0 - 47
include/iterator/detail/traits.h

@@ -1,47 +0,0 @@
-#pragma once
-
-#include <algorithm>
-#include <iterator>
-#include <type_traits>
-
-#include <iterator/forwards.h>
-
-#include <iterator/detail/macro.h>
-
-// Section: Non-Dependant Typedef Helpers
-namespace iterator::detail {
-template <typename Iter>
-using category_t = typename std::iterator_traits<Iter>::iterator_category;
-template <typename C> using iter = decltype(std::begin(std::declval<C>()));
-}
-
-namespace iterator::detail {
-// Type Helper for identifying container-like objects
-template <typename C, typename = void> struct is_container : std::false_type {};
-template <typename C>
-struct is_container<C, std::void_t<iter<C>>> : std::true_type {};
-
-template <typename It, typename = void>
-struct sentinel_type {
-  using type = void;
-};
-template <typename It>
-struct sentinel_type<It, std::void_t<typename It::sentinel_type>> {
-  using type = typename It::sentinel_type;
-};
-}
-
-namespace iterator::detail {
-template <typename C> constexpr bool is_container_v = is_container<C>{};
-
-template <typename Iter>
-constexpr bool is_rvalue_iterator_v = !std::is_reference_v<DEREF_TYPE(Iter)>;
-
-template <typename It>
-constexpr bool has_sentinel_type_v = !std::is_void_v<typename sentinel_type<It>::type>;
-
-template <typename It, typename S>
-constexpr bool is_sentinel_v = std::is_same_v<typename sentinel_type<It>::type, S>;
-}
-
-#include <iterator/detail/undef.h>

+ 3 - 10
include/iterator/end_aware_iterator.h

@@ -7,7 +7,6 @@
 
 #pragma once
 
-#include <iterator/detail/traits.h>
 #include <iterator/forwards.h>
 #include <iterator/proxy.h>
 #include <iterator/sentinel.h>
@@ -31,12 +30,8 @@ public:
   end_aware_iterator() = default;
   end_aware_iterator(It it, It end) : super_t(it), end_(end) {}
 
-  template <typename C, REQUIRES(detail::is_container_v<C>)>
-  end_aware_iterator(C && container)
-      : super_t(std::begin(container)), end_(std::end(container)) {
-    static_assert(std::is_reference_v<C>,
-                  "Cannot access iterator of a temporary");
-  }
+  end_aware_iterator(Range auto & container)
+      : super_t(std::begin(container)), end_(std::end(container)) {}
 
   template <typename Ot>
   end_aware_iterator(end_aware_iterator<Ot> const & other)
@@ -63,13 +58,11 @@ private:
 };
 
 template <typename C>
-end_aware_iterator(C &&) -> end_aware_iterator<detail::iter<C>>;
+end_aware_iterator(C &&) -> end_aware_iterator<iterator_t<C>>;
 template <typename It> end_aware_iterator(It, It) -> end_aware_iterator<It>;
 template <typename It>
 end_aware_iterator(end_aware_iterator<It>, end_aware_iterator<It>)
     -> end_aware_iterator<It>;
 }
 
-MAKE_ITERATOR_FACADE_TYPEDEFS_T(::iterator::end_aware_iterator);
-
 #include <iterator/detail/undef.h>

+ 0 - 1
include/iterator/facade.h

@@ -6,7 +6,6 @@
 
 #include <iterator/concepts.h>
 #include <iterator/detail/arrow_proxy.h>
-#include <iterator/detail/traits.h>
 
 #include <iterator/detail/macro.h>
 

+ 4 - 8
include/iterator/filter_iterator.h

@@ -9,7 +9,6 @@
 
 #include <functional>
 
-#include <iterator/detail/traits.h>
 #include <iterator/end_aware_iterator.h>
 #include <iterator/facade.h>
 #include <iterator/forwards.h>
@@ -27,9 +26,8 @@ public:
 public:
   filter_iterator() = default;
 
-  template <typename C, REQUIRES(detail::is_container_v<C>)>
-  filter_iterator(C && c, Pred pred)
-      : base_(std::forward<C>(c)), pred_(std::move(pred)) {
+  filter_iterator(Range auto & c, Pred pred)
+      : base_(c), pred_(std::move(pred)) {
     if (should_advance()) { increment(); }
   }
 
@@ -72,13 +70,11 @@ public:
 };
 
 template <typename C, typename P>
-filter_iterator(C &&, P) -> filter_iterator<detail::iter<C>, P>;
+filter_iterator(C &, P) -> filter_iterator<iterator_t<C>, P>;
 template <typename It, typename P>
-filter_iterator(P, end_aware_iterator<It>, P) -> filter_iterator<It, P>;
+filter_iterator(end_aware_iterator<It>, P) -> filter_iterator<It, P>;
 template <typename It, typename P>
 filter_iterator(It, It, P) -> filter_iterator<It, P>;
 }
 
-MAKE_ITERATOR_FACADE_TYPEDEFS_T(::iterator::filter_iterator);
-
 #include <iterator/detail/undef.h>

+ 1 - 1
include/iterator/indexed_iterator.h

@@ -59,7 +59,7 @@ public:
     return other.base_ - base_;
   }
 
-  SFINAE(detail::has_sentinel_type_v<It>) bool at_end() const {
+  bool at_end() const requires(has_sentinel<It>) {
     return base_ == typename It::sentinel_type();
   }
 

+ 4 - 7
include/iterator/join_iterator.h

@@ -24,7 +24,7 @@ class joining_iterator
     : public facade<joining_iterator<It>> {
 private:
   template <typename Ot> friend class joining_iterator;
-  constexpr static bool requires_caching = detail::is_rvalue_iterator_v<It>;
+  constexpr static bool requires_caching = !std::is_reference_v<DEREF_TYPE(It)>;
 
 public:
   using sentinel_type = sentinel_t;
@@ -33,7 +33,7 @@ public:
                          capture_iterator<end_aware_iterator<It>>,
                          end_aware_iterator<It>>;
   using inner_iterator_t =
-      end_aware_iterator<detail::iter<DEREF_TYPE(outer_iterator_t)>>;
+      end_aware_iterator<iterator_t<DEREF_TYPE(outer_iterator_t)>>;
 
 private:
   outer_iterator_t outer_;
@@ -47,8 +47,7 @@ public:
     safely_init_inner_iterator(other.outer_, other.inner_);
   }
 
-  template <typename C, REQUIRES(detail::is_container_v<C>)>
-  joining_iterator(C && container) : outer_(FWD(container)) {
+  joining_iterator(Range auto & container) : outer_(FWD(container)) {
     update_iterator();
   }
 
@@ -99,11 +98,9 @@ private:
 };
 
 template <typename C>
-joining_iterator(C &&) -> joining_iterator<detail::iter<C>>;
+joining_iterator(C &) -> joining_iterator<iterator_t<C>>;
 template <typename JI>
 joining_iterator(end_aware_iterator<JI>) -> joining_iterator<JI>;
 }
 
-MAKE_ITERATOR_FACADE_TYPEDEFS_T(::iterator::joining_iterator);
-
 #include <iterator/detail/undef.h>

+ 5 - 6
include/iterator/proxy.h

@@ -22,7 +22,7 @@ public:
   decltype(auto) dereference() const { return *impl_; }
   void increment() { ++impl_; }
   bool equal_to(Self const & other) const { return impl_ == other.impl_; }
-  SFINAE(detail::has_sentinel_type_v<It>) bool at_end() const {
+  bool at_end() const requires(has_sentinel<It>) {
     return impl() == typename It::sentinel_type();
   }
 
@@ -44,7 +44,7 @@ public:
   decltype(auto) dereference() const { return *impl_; }
   void increment() { ++impl_; }
   bool equal_to(Self const & other) const { return impl_ == other.impl_; }
-  SFINAE(detail::has_sentinel_type_v<It>) bool at_end() const {
+  bool at_end() const requires(has_sentinel<It>) {
     return impl() == typename It::sentinel_type();
   }
 
@@ -67,7 +67,7 @@ public:
   void increment() { ++impl_; }
   void decrement() { --impl_; }
   bool equal_to(Self const & other) const { return impl_ == other.impl_; }
-  SFINAE(detail::has_sentinel_type_v<It>) bool at_end() const {
+  bool at_end() const requires(has_sentinel<It>) {
     return impl() == typename It::sentinel_type();
   }
 
@@ -96,12 +96,11 @@ public:
     return other.impl_ - impl_;
   }
   
-  template <typename S, REQUIRES((detail::is_sentinel_v<It, S>))>
-  friend auto operator-(S sentinel, Self const &self) {
+  friend auto operator-(sentinel_for<It> auto sentinel, Self const &self) {
     return sentinel - self.impl();
   }
   
-  SFINAE(detail::has_sentinel_type_v<It>) bool at_end() const {
+  bool at_end() const requires(has_sentinel<It>) {
     return (typename It::sentinel_type() - impl()) <= 0;
   }
 

+ 11 - 11
include/iterator/recursive_iterator.h

@@ -19,21 +19,21 @@
 #include <iterator/detail/macro.h>
 
 namespace iterator::recursive {
+struct unbounded {
+  template <typename It>
+  static constexpr recursion_type const value = iter_typeclass<It>;
+  using next = unbounded;
+  static constexpr size_t size = std::numeric_limits<size_t>::max();
+};
+
 template <size_t N, size_t I> struct bounded {
   template <typename It>
   static constexpr recursion_type const value =
-      I == N ? recursion_type::END : typeclass_t<It>::value;
+      I == N ? recursion_type::END : iter_typeclass<It>;
   using next = std::conditional_t<I == N, void, bounded<N, I + 1>>;
   static constexpr size_t size = N;
 };
 
-struct unbounded {
-  template <typename It>
-  static constexpr recursion_type const value = typeclass_t<It>::value;
-  using next = unbounded;
-  static constexpr size_t size = std::numeric_limits<size_t>::max();
-};
-
 template <typename It, typename Bnd = unbounded,
           recursion_type = Bnd::template value<It>>
 struct tuple;
@@ -42,7 +42,7 @@ template <typename It, typename Bnd>
 struct tuple<It, Bnd, recursion_type::END> {
   using iter = std::tuple<end_aware_iterator<It>>;
   decltype(auto) get(It iter) const {
-    if constexpr (is_associative<It>{}) {
+    if constexpr (associative_value<std::iter_value_t<It>>) {
       return std::tie(iter->first, iter->second);
     } else {
       return std::tie(*iter);
@@ -199,12 +199,12 @@ auto get(::iterator::recursive_iterator_n<It, N> const & iter) {
 }
 
 template <typename C> auto make_recursive_iterator(C && collect) {
-  return iterator::recursive_iterator<iterator::detail::iter<C>>(collect);
+  return iterator::recursive_iterator<iterator::iterator_t<C>>(collect);
 }
 
 template <std::size_t Max, typename C>
 auto make_recursive_iterator(C && collect) {
-  return iterator::recursive_iterator_n<iterator::detail::iter<C>, Max>(
+  return iterator::recursive_iterator_n<iterator::iterator_t<C>, Max>(
       collect);
 }
 

+ 0 - 4
iterator.xcodeproj/project.pbxproj

@@ -15,7 +15,6 @@
 		CD41AFE82E7F13E4004F3E51 /* arrow_proxy.h in Headers */ = {isa = PBXBuildFile; fileRef = CDA2B61A2858128C004D5353 /* arrow_proxy.h */; };
 		CD41AFE92E7F13E4004F3E51 /* macro.h in Headers */ = {isa = PBXBuildFile; fileRef = CD5AEB3129D8885400A390A4 /* macro.h */; };
 		CD41AFEA2E7F13E4004F3E51 /* recursive_traits.h in Headers */ = {isa = PBXBuildFile; fileRef = CDA2B6182858128C004D5353 /* recursive_traits.h */; };
-		CD41AFEB2E7F13E4004F3E51 /* traits.h in Headers */ = {isa = PBXBuildFile; fileRef = CDA2B6192858128C004D5353 /* traits.h */; };
 		CD41AFEC2E7F13E4004F3E51 /* undef.h in Headers */ = {isa = PBXBuildFile; fileRef = CD5AEB3229D8886200A390A4 /* undef.h */; };
 		CD41AFED2E7F13E4004F3E51 /* capture_iterator.h in Headers */ = {isa = PBXBuildFile; fileRef = CD5AEB3329D8956600A390A4 /* capture_iterator.h */; };
 		CD41AFEE2E7F13E4004F3E51 /* end_aware_iterator.h in Headers */ = {isa = PBXBuildFile; fileRef = CDA2B61B2858128C004D5353 /* end_aware_iterator.h */; };
@@ -95,7 +94,6 @@
 		CDA2B6152858128C004D5353 /* unkeyed_iterator.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = unkeyed_iterator.h; sourceTree = "<group>"; };
 		CDA2B6162858128C004D5353 /* recursive_iterator.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = recursive_iterator.h; sourceTree = "<group>"; };
 		CDA2B6182858128C004D5353 /* recursive_traits.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = recursive_traits.h; sourceTree = "<group>"; };
-		CDA2B6192858128C004D5353 /* traits.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = traits.h; sourceTree = "<group>"; };
 		CDA2B61A2858128C004D5353 /* arrow_proxy.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = arrow_proxy.h; sourceTree = "<group>"; };
 		CDA2B61B2858128C004D5353 /* end_aware_iterator.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = end_aware_iterator.h; sourceTree = "<group>"; };
 		CDA2B61C2858128C004D5353 /* proxy.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = proxy.h; sourceTree = "<group>"; };
@@ -216,7 +214,6 @@
 				CDA2B61A2858128C004D5353 /* arrow_proxy.h */,
 				CD5AEB3129D8885400A390A4 /* macro.h */,
 				CDA2B6182858128C004D5353 /* recursive_traits.h */,
-				CDA2B6192858128C004D5353 /* traits.h */,
 				CD5AEB3229D8886200A390A4 /* undef.h */,
 			);
 			path = detail;
@@ -264,7 +261,6 @@
 				CD41AFE82E7F13E4004F3E51 /* arrow_proxy.h in Headers */,
 				CD41AFE92E7F13E4004F3E51 /* macro.h in Headers */,
 				CD41AFEA2E7F13E4004F3E51 /* recursive_traits.h in Headers */,
-				CD41AFEB2E7F13E4004F3E51 /* traits.h in Headers */,
 				CD41AFEC2E7F13E4004F3E51 /* undef.h in Headers */,
 				CD41AFED2E7F13E4004F3E51 /* capture_iterator.h in Headers */,
 				CD41AFEE2E7F13E4004F3E51 /* end_aware_iterator.h in Headers */,