Jelajahi Sumber

Alter recursive iterator w.r.t. new facade code.

Sam Jaffe 4 tahun lalu
induk
melakukan
013f9c4155

+ 13 - 10
include/iterator/detail/flatten_iterator_layer.hpp

@@ -1,5 +1,6 @@
 #pragma once
 
+#include "arrow_proxy.h"
 #include "recursive_iterator_base.hpp"
 #include "recursive_iterator_traits.hpp"
 
@@ -36,13 +37,13 @@ namespace iterator { namespace detail {
                                 std::declval<next_value_type>()));
     using reference = decltype(std::tuple_cat(
         std::tie(std::declval<key_type>()), std::declval<next_reference>()));
-    using pointer = void;
-    using difference_type = typename super::difference_type;
+    using pointer = detail::arrow_proxy<reference>;
+    using difference_type = std::ptrdiff_t;
     using iterator_category = std::forward_iterator_tag;
 
   public:
     flatten_iterator_layer() = default;
-    flatten_iterator_layer(layer v) : flatten_iterator_layer() {
+    explicit flatten_iterator_layer(layer v) : flatten_iterator_layer() {
       assign(v);
       update();
     }
@@ -61,7 +62,7 @@ namespace iterator { namespace detail {
      * sub-aggregates of pair/tuple type. Similarly, forward_as_tuple means
      * even a key-type of pair/tuple will not be unwrapped.
      */
-    reference operator*() const {
+    decltype(auto) operator*() const {
       return std::tuple_cat(std::forward_as_tuple(std::get<0>(layer::get())),
                             next_reference(super::get()));
     }
@@ -70,14 +71,16 @@ namespace iterator { namespace detail {
      * Unimplemented because we return an inline constructed type, and tuple
      * can only be accessed through std::get anyway.
      */
-    pointer operator->() const;
+    //    auto operator->() const { return detail::arrow_proxy(**this); }
+    void operator->() const;
 
     bool operator==(flatten_iterator_layer const & other) const {
-      return layer::operator==(other) && super::operator==(other);
+      return (static_cast<layer const &>(*this) == other) &&
+             (static_cast<super const &>(*this) == other);
     }
 
   protected:
-    reference get() const { return operator*(); }
+    decltype(auto) get() const { return **this; }
 
     /**
      * @copydoc recursive_iterator_layer::next
@@ -89,7 +92,7 @@ namespace iterator { namespace detail {
 
     void update() {
       layer & self = static_cast<layer &>(*this);
-      while (super::done() && !(++self).done()) {
+      while (super::at_end() && !(++self).at_end()) {
         super::assign(make_end_aware_iterator(self->second));
       }
     }
@@ -99,9 +102,9 @@ namespace iterator { namespace detail {
      */
     void assign(layer v) {
       static_cast<layer &>(*this) = v;
-      if (!v.done()) { super::assign(make_end_aware_iterator(v->second)); }
+      if (!v.at_end()) { super::assign(make_end_aware_iterator(v->second)); }
     }
 
-    bool done() const { return layer::done(); }
+    using layer::at_end;
   };
 }}

+ 7 - 1
include/iterator/detail/recursive_iterator_base.hpp

@@ -19,6 +19,9 @@ namespace iterator { namespace detail {
 
   protected:
     using recursive_category = terminal_layer_tag_t;
+    using reference = decltype(*std::declval<super>());
+    using value_type = std::remove_cv_t<std::remove_reference_t<reference>>;
+    using pointer = decltype(std::declval<super>().operator->());
 
   public:
     using super::super;
@@ -27,7 +30,7 @@ namespace iterator { namespace detail {
     recursive_iterator_base() = default;
 
   protected:
-    typename super::reference get() const { return super::operator*(); }
+    decltype(auto) get() const { return super::operator*(); }
   };
 
   /**
@@ -65,6 +68,9 @@ namespace iterator { namespace detail {
     recursive_iterator_base(super && iter) : super(std::move(iter)) {}
     recursive_iterator_base() = default;
 
+    // TODO: Get rid of this again
+    reference operator*() const { return get(); }
+
   protected:
     /**
      * An alternative function to operator*(), which allows single layer

+ 13 - 13
include/iterator/detail/recursive_iterator_layer.hpp

@@ -29,15 +29,15 @@ namespace iterator { namespace detail {
     using recursive_category = continue_layer_tag_t;
 
   public:
-    using value_type = typename super::value_type;
-    using reference = typename super::reference;
-    using pointer = typename super::pointer;
-    using difference_type = typename super::difference_type;
+    using reference = decltype(*std::declval<super>());
+    using value_type = std::remove_cv_t<std::remove_reference_t<reference>>;
+    using pointer = decltype(std::declval<super>().operator->());
+    using difference_type = std::ptrdiff_t;
     using iterator_category = std::forward_iterator_tag;
 
   public:
     recursive_iterator_layer() = default;
-    recursive_iterator_layer(layer v) : recursive_iterator_layer() {
+    explicit recursive_iterator_layer(layer v) : recursive_iterator_layer() {
       assign(v);
       update();
     }
@@ -46,16 +46,16 @@ namespace iterator { namespace detail {
         : layer(static_cast<recursive_iterator_base<OIter> const &>(other)),
           super(static_cast<Rec const &>(other)) {}
 
-    reference operator*() const { return super::get(); }
-
-    pointer operator->() const { return super::operator->(); }
+    decltype(auto) operator*() const { return super::get(); }
+    decltype(auto) operator->() const { return super::operator->(); }
 
     bool operator==(recursive_iterator_layer const & other) const {
-      return layer::operator==(other) && super::operator==(other);
+      return (static_cast<layer const &>(*this) == other) &&
+             (static_cast<super const &>(*this) == other);
     }
 
   protected:
-    reference get() const { return operator*(); }
+    decltype(auto) get() const { return operator*(); }
 
     /**
      * Advance the iterator step. If the next layer has reached the end, then
@@ -74,16 +74,16 @@ namespace iterator { namespace detail {
      */
     void assign(layer v) {
       static_cast<layer &>(*this) = v;
-      if (!v.done()) { super::assign(make_end_aware_iterator(*v)); }
+      if (!v.at_end()) { super::assign(make_end_aware_iterator(*v)); }
     }
 
     void update() {
       layer & self = static_cast<layer &>(*this);
-      while (super::done() && !(++self).done()) {
+      while (super::at_end() && !(++self).at_end()) {
         super::assign(make_end_aware_iterator(*self));
       }
     }
 
-    bool done() const { return layer::done(); }
+    using layer::at_end;
   };
 }}

+ 2 - 4
include/iterator/detail/recursive_iterator_traits.hpp

@@ -6,6 +6,7 @@
 #include <utility>
 
 #include "../iterator_fwd.hpp"
+#include "traits.h"
 
 namespace iterator { namespace detail {
   template <typename Iterator, typename RecursiveIterator_NextLayer>
@@ -50,8 +51,6 @@ namespace iterator { namespace detail {
   // Type deduction guides for constructing recursive iterators.
   enum class typeclass { TERMINAL, CONTAINER, ASSOCIATIVE_CONTAINER };
 
-  template <typename> struct void_t { using type = void; };
-
   template <typename T, typename = void> struct typeclass_t {
     static constexpr typeclass const value{typeclass::TERMINAL};
   };
@@ -74,8 +73,7 @@ namespace iterator { namespace detail {
     static constexpr typeclass const value{typeclass::TERMINAL};
   };
 
-  template <typename T>
-  struct typeclass_t<T, typename void_t<mapped_iterator<T>>::type> {
+  template <typename T> struct typeclass_t<T, void_t<mapped_iterator<T>>> {
     static constexpr typeclass const value{typeclass::ASSOCIATIVE_CONTAINER};
   };
 

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

@@ -5,4 +5,24 @@
 
 namespace iterator::detail {
   template <typename> using void_t = void;
+
+  template <typename T, typename = void> struct reference_helper {
+    using type = decltype(*std::declval<T>());
+  };
+  template <typename T>
+  struct reference_helper<T, void_t<typename T::reference>> {
+    using type = typename T::reference;
+  };
+
+  template <typename T, typename = void> struct value_type_helper {
+    using reference = typename reference_helper<T>::type;
+    using type = std::remove_cv_t<std::remove_reference_t<reference>>;
+  };
+  template <typename T>
+  struct value_type_helper<T, void_t<typename T::value_type>> {
+    using type = typename T::value_type;
+  };
+
+  template <typename T> using value_type = typename value_type_helper<T>::type;
+  template <typename T> using reference = typename reference_helper<T>::type;
 }

+ 16 - 6
include/iterator/recursive_iterator.hpp

@@ -11,6 +11,7 @@
 
 #include "detail/recursive_iterator_impl.hpp"
 #include "detail/recursive_iterator_traits.hpp"
+#include "detail/traits.h"
 #include "iterator_fwd.hpp"
 
 namespace iterator {
@@ -31,6 +32,11 @@ namespace iterator {
   class recursive_iterator : public detail::recursive_iterator_impl<Iterator> {
   public:
     using super = detail::recursive_iterator_impl<Iterator>;
+    using reference = decltype(*std::declval<super>());
+    using value_type = std::remove_cv_t<std::remove_reference_t<reference>>;
+    using pointer = decltype(std::declval<super>().operator->());
+    using difference_type = std::ptrdiff_t;
+    using iterator_category = std::forward_iterator_tag;
 
   public:
     using super::super;
@@ -48,7 +54,7 @@ namespace iterator {
     }
 
     bool operator!=(recursive_iterator const & other) const {
-      return !(super::operator==(other));
+      return !(static_cast<super const &>(*this) == other);
     }
   };
 
@@ -92,7 +98,7 @@ namespace iterator {
     }
 
     bool operator!=(recursive_iterator_n const & other) const {
-      return !(super::operator==(other));
+      return !(static_cast<super const &>(*this) == other);
     }
   };
 }
@@ -117,23 +123,27 @@ namespace std {
 template <typename C>
 auto make_recursive_iterator(C & collect)
     -> iterator::recursive_iterator<decltype(std::begin(collect))> {
-  return {make_end_aware_iterator(collect)};
+  return iterator::recursive_iterator<decltype(std::begin(collect))>{
+      make_end_aware_iterator(collect)};
 }
 
 template <typename C>
 auto make_recursive_iterator(C const & collect)
     -> iterator::recursive_iterator<decltype(std::begin(collect))> {
-  return {make_end_aware_iterator(collect)};
+  return iterator::recursive_iterator<decltype(std::begin(collect))>{
+      make_end_aware_iterator(collect)};
 }
 
 template <std::size_t Max, typename C>
 auto make_recursive_iterator(C & collect)
     -> iterator::recursive_iterator_n<decltype(std::begin(collect)), Max> {
-  return {make_end_aware_iterator(collect)};
+  return iterator::recursive_iterator_n<decltype(std::begin(collect)), Max>{
+      make_end_aware_iterator(collect)};
 }
 
 template <std::size_t Max, typename C>
 auto make_recursive_iterator(C const & collect)
     -> iterator::recursive_iterator_n<decltype(std::begin(collect)), Max> {
-  return {make_end_aware_iterator(collect)};
+  return iterator::recursive_iterator_n<decltype(std::begin(collect)), Max>{
+      make_end_aware_iterator(collect)};
 }