Kaynağa Gözat

Move traits elsewhere.

Sam Jaffe 4 yıl önce
ebeveyn
işleme
aca67cbf62

+ 52 - 0
include/iterator/detail/recursive_traits.h

@@ -0,0 +1,52 @@
+#pragma once
+
+#include <iterator>
+
+#include "traits.h"
+
+namespace iterator::recursive {
+  // Type deduction guides for constructing recursive iterators.
+  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 T> using val_key_t = typename T::value_type::first_type;
+
+  // 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<val_key_t<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 T> struct typeclass_t<T, detail::void_t<mapped<T>>> {
+    constexpr static recursion_type value{recursion_type::ASSOC};
+  };
+}

+ 9 - 56
include/iterator/recursive_iterator.hpp

@@ -9,83 +9,36 @@
 
 #include "iterator_fwd.hpp"
 
-#include <iterator>
 #include <string>
 #include <tuple>
 #include <utility>
 
-#include "detail/traits.h"
+#include "detail/recursive_traits.h"
 #include "end_aware_iterator.hpp"
 #include "facade.h"
 
-namespace iterator::recursive {
-  // Helpers for condensing type deductions
-  template <typename IterType>
-  using value = decltype(std::begin(*std::declval<IterType>()));
-
-  template <typename IterType>
-  using mapped = decltype(std::begin(std::declval<IterType>()->second));
-
-  // 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<
-                               typename T::value_type::first_type>::value>>
-      : std::true_type {};
-
-  // Type deduction guides for constructing recursive iterators.
-  enum class typeclass { TERMINAL, CONTAINER, ASSOCIATIVE_CONTAINER };
-
-  template <typename T, typename = void> struct typeclass_t {
-    static constexpr typeclass const value{typeclass::TERMINAL};
-  };
-
-  template <typename T> struct is_string_iterator : std::false_type {};
-  template <>
-  struct is_string_iterator<std::string::iterator> : std::true_type {};
-  template <>
-  struct is_string_iterator<std::string::const_iterator> : std::true_type {};
-
-  template <typename T>
-  struct typeclass_t<T,
-                     std::enable_if_t<!is_string_iterator<value<T>>::value>> {
-    static constexpr typeclass const value{typeclass::CONTAINER};
-  };
-
-  template <typename T>
-  struct typeclass_t<T, std::enable_if_t<is_string_iterator<value<T>>::value>> {
-    static constexpr typeclass const value{typeclass::TERMINAL};
-  };
-
-  template <typename T> struct typeclass_t<T, detail::void_t<mapped<T>>> {
-    static constexpr typeclass const value{typeclass::ASSOCIATIVE_CONTAINER};
-  };
-}
-
 namespace iterator::recursive {
   template <size_t N, size_t I = 1> struct bounded {
     template <typename It>
-    static constexpr typeclass const value =
-        I == N ? typeclass::TERMINAL : typeclass_t<It>::value;
+    static constexpr recursion_type const value =
+        I == N ? recursion_type::END : typeclass_t<It>::value;
     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 typeclass const value = typeclass_t<It>::value;
+    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,
-            typeclass = Bnd::template value<It>>
+            recursion_type = Bnd::template value<It>>
   struct tuple;
 
   template <typename It, typename Bnd>
-  struct tuple<It, Bnd, typeclass::TERMINAL> {
+  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>{}) {
@@ -100,7 +53,7 @@ namespace iterator::recursive {
   using tuple_cat_t = decltype(std::tuple_cat(std::declval<Ts>()...));
 
   template <typename It, typename Bnd>
-  struct tuple<It, Bnd, typeclass::CONTAINER> {
+  struct tuple<It, Bnd, recursion_type::THRU> {
     using next = decltype(std::begin(*std::declval<It>()));
     using iter = tuple_cat_t<std::tuple<end_aware_iterator<It>>,
                              typename tuple<next, typename Bnd::next>::iter>;
@@ -108,7 +61,7 @@ namespace iterator::recursive {
   };
 
   template <typename It, typename Bnd>
-  struct tuple<It, Bnd, typeclass::ASSOCIATIVE_CONTAINER> {
+  struct tuple<It, Bnd, recursion_type::ASSOC> {
     using next = decltype(std::begin(std::declval<It>()->second));
     using iter = tuple_cat_t<std::tuple<end_aware_iterator<It>>,
                              typename tuple<next, typename Bnd::next>::iter>;
@@ -173,7 +126,7 @@ namespace iterator::recursive {
       // iteration to be had.
       auto it = std::get<I>(impl_);
       if constexpr (I == size - 1) {
-        return tuple<decltype(it), unbounded, typeclass::TERMINAL>{}.get(it);
+        return tuple<decltype(it), unbounded, recursion_type::END>{}.get(it);
       } else {
         // Implemented as a recursive function instead of a parameter-pack
         // because OSX has a compiler bug regarding certain forms of parameter