Просмотр исходного кода

Improve type system, add overrides that mark std::string as terminal in all cases.

Sam Jaffe 5 лет назад
Родитель
Сommit
46e766570a

+ 20 - 16
include/iterator/detail/recursive_iterator_impl.hpp

@@ -13,6 +13,16 @@
 #include "recursive_iterator_traits.hpp"
 
 namespace iterator { namespace detail {
+  template <typename Iterator, typeclass = typeclass_t<Iterator>::value>
+  class recursive_iterator_impl;
+
+  /**
+   * A bounded_recursive_iterator_impl where N == Max is always a terminal node.
+   */
+  template <typename Iterator, std::size_t N, std::size_t Max,
+            typeclass = std::conditional_t<N == Max, typeclass_t<void>,
+                                           typeclass_t<Iterator>>::value>
+  class bounded_recursive_iterator_impl;
 
   /**
    * @class recursive_iterator_impl
@@ -23,8 +33,9 @@ namespace iterator { namespace detail {
    * @tparam Iterator The iterator type being processed, such as
    * std::vector<int>::iterator
    */
-  template <typename Iterator, typename = void>
-  class recursive_iterator_impl : public recursive_iterator_base<Iterator> {
+  template <typename Iterator>
+  class recursive_iterator_impl<Iterator, typeclass::TERMINAL>
+      : public recursive_iterator_base<Iterator> {
   public:
     using super = recursive_iterator_base<Iterator>;
 
@@ -45,8 +56,7 @@ namespace iterator { namespace detail {
    * @see recursive_iterator_layer
    */
   template <typename Iterator>
-  class recursive_iterator_impl<Iterator,
-                                typename void_t<value_iterator<Iterator>>::type>
+  class recursive_iterator_impl<Iterator, typeclass::CONTAINER>
       : public recursive_iterator_layer<
             Iterator, recursive_iterator_impl<value_iterator<Iterator>>> {
   public:
@@ -75,8 +85,7 @@ namespace iterator { namespace detail {
    * @see flatten_iterator_layer
    */
   template <typename Iterator>
-  class recursive_iterator_impl<
-      Iterator, typename void_t<mapped_iterator<Iterator>>::type>
+  class recursive_iterator_impl<Iterator, typeclass::ASSOCIATIVE_CONTAINER>
       : public flatten_iterator_layer<
             Iterator, recursive_iterator_impl<mapped_iterator<Iterator>>> {
   public:
@@ -100,8 +109,8 @@ namespace iterator { namespace detail {
    * @tparam Max The maximum recursive depth to dive down, in case you need to
    * process some sub-collection in a specific manner.
    */
-  template <typename Iterator, std::size_t N, std::size_t Max, typename = void>
-  class bounded_recursive_iterator_impl
+  template <typename Iterator, std::size_t N, std::size_t Max>
+  class bounded_recursive_iterator_impl<Iterator, N, Max, typeclass::TERMINAL>
       : public recursive_iterator_base<Iterator> {
   public:
     using super = recursive_iterator_base<Iterator>;
@@ -123,10 +132,7 @@ namespace iterator { namespace detail {
    * @see recursive_iterator_layer
    */
   template <typename Iterator, std::size_t N, std::size_t Max>
-      class bounded_recursive_iterator_impl < Iterator,
-      N, Max,
-      typename std::enable_if<
-          N<Max, typename void_t<value_iterator<Iterator>>::type>::type>
+  class bounded_recursive_iterator_impl<Iterator, N, Max, typeclass::CONTAINER>
       : public recursive_iterator_layer<
             Iterator, bounded_recursive_iterator_impl<value_iterator<Iterator>,
                                                       N + 1, Max>> {
@@ -157,10 +163,8 @@ namespace iterator { namespace detail {
    * @see flatten_iterator_layer
    */
   template <typename Iterator, std::size_t N, std::size_t Max>
-      class bounded_recursive_iterator_impl < Iterator,
-      N, Max,
-      typename std::enable_if<
-          N<Max, typename void_t<mapped_iterator<Iterator>>::type>::type>
+  class bounded_recursive_iterator_impl<Iterator, N, Max,
+                                        typeclass::ASSOCIATIVE_CONTAINER>
       : public flatten_iterator_layer<
             Iterator, bounded_recursive_iterator_impl<mapped_iterator<Iterator>,
                                                       N + 1, Max>> {

+ 27 - 0
include/iterator/detail/recursive_iterator_traits.hpp

@@ -1,6 +1,7 @@
 #pragma once
 
 #include <iterator>
+#include <string>
 #include <tuple>
 #include <utility>
 
@@ -38,4 +39,30 @@ namespace iterator { namespace detail {
 
   template <typename T>
   using is_associative_t = std::enable_if_t<is_associative<T>::value>;
+
+  /**
+   * 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 <>
+  struct typeclass_t<typename std::string::iterator> : typeclass_t<void> {};
+  template <>
+  struct typeclass_t<typename std::string::const_iterator> : typeclass_t<void> {
+  };
+
+  template <typename T>
+  struct typeclass_t<T, typename void_t<value_iterator<T>>::type> {
+    static constexpr typeclass const value{typeclass::CONTAINER};
+  };
+
+  template <typename T>
+  struct typeclass_t<T, typename void_t<mapped_iterator<T>>::type> {
+    static constexpr typeclass const value{typeclass::ASSOCIATIVE_CONTAINER};
+  };
+
 }}