瀏覽代碼

fix: compiler errors and test errors

Sam Jaffe 2 年之前
父節點
當前提交
42718949c2

+ 3 - 3
include/iterator/detail/recursive_traits.h

@@ -14,14 +14,14 @@ 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;
+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<val_key_t<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 {
@@ -45,7 +45,7 @@ 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>>> {
+template <typename T> struct typeclass_t<T, std::void_t<mapped<T>>> {
   constexpr static recursion_type value{recursion_type::ASSOC};
 };
 }

+ 6 - 3
include/iterator/join_iterator.hpp

@@ -20,12 +20,12 @@ template <typename Iter, typename = void> class iterator {
 protected:
   using inner_t = decltype(*std::declval<Iter>());
 
-protected:
+public:
   iterator() = default;
 
   template <typename I>
   iterator(iterator<I> const & other)
-      : iterator(other.join_iterator(), other.element_iterator()) {}
+      : iterator(other.joiner_, other.element_) {}
 
   template <typename C, typename = std::enable_if_t<detail::is_container_v<C>>>
   iterator(C && container)
@@ -39,6 +39,7 @@ protected:
     if (update) { update_iterator(); }
   }
 
+protected:
   void update_iterator() {
     while (!joiner_.at_end() &&
            (element_ = end_aware_iterator(*joiner_)).at_end()) {
@@ -47,6 +48,7 @@ protected:
   }
 
 protected:
+  template <typename, typename> friend class iterator;
   end_aware_iterator<Iter> joiner_;
   end_aware_iterator<iter<inner_t>> element_;
 };
@@ -56,7 +58,7 @@ class iterator<Iter, std::enable_if_t<detail::is_rvalue_iterator_v<Iter>>> {
 protected:
   using inner_t = decltype(*std::declval<Iter>());
 
-protected:
+public:
   iterator() = default;
   template <typename C, typename = std::enable_if_t<detail::is_container_v<C>>>
   iterator(C && container) : joiner_(std::forward<C>(container)) {
@@ -65,6 +67,7 @@ protected:
 
   iterator(end_aware_iterator<Iter> join) : joiner_(join) { update_iterator(); }
 
+protected:
   void update_iterator() {
     while (!joiner_.at_end() && sync().at_end()) {
       ++joiner_;

+ 19 - 11
include/iterator/recursive_iterator.hpp

@@ -83,13 +83,16 @@ struct tuple<It, Bnd, recursion_type::ASSOC> {
  */
 template <typename It, typename Bnd>
 class rimpl : public facade<rimpl<It, Bnd>> {
+public:
+  using iters_t = typename tuple<It, Bnd>::iter;
+  static constexpr size_t n_iters =
+      std::tuple_size_v<typename tuple<It, Bnd>::iter>;
+  static constexpr size_t size = std::min(n_iters, Bnd::size);
+
 private:
-  typename tuple<It, Bnd>::iter impl_;
+  iters_t impl_;
 
 public:
-  static constexpr size_t size =
-      std::min(std::tuple_size_v<typename tuple<It, Bnd>::iter>, Bnd::size);
-
   rimpl() = default;
   rimpl(end_aware_iterator<It> iter) { assign<0>(iter); }
   template <typename Ot>
@@ -132,22 +135,27 @@ public:
   auto const & impl() const { return impl_; }
 
 private:
-  template <size_t I = 0> decltype(auto) build_tuple() const {
+  template <size_t I> decltype(auto) get() const {
+    auto it = std::get<I>(impl_);
     // In the case of a bounded recursive iterator, I need to ensure that the
     // effectively terminal iterator is treated as such even if there is still
     // iteration to be had.
-    auto it = std::get<I>(impl_);
     if constexpr (I == size - 1) {
       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
-      // packs...
-      return std::tuple_cat(tuple<decltype(it)>{}.get(it),
-                            build_tuple<I + 1>());
+      return tuple<decltype(it)>{}.get(it);
     }
   }
 
+  template <size_t... Is>
+  decltype(auto) build_tuple(std::index_sequence<Is...>) const {
+    return std::tuple_cat(get<Is>()...);
+  }
+
+  decltype(auto) build_tuple() const {
+    return build_tuple(std::make_index_sequence<size>());
+  }
+
   template <size_t I, typename C> void assign(end_aware_iterator<C> it) {
     std::get<I>(impl_) = it;
     if constexpr (I < size - 1) {

+ 2 - 18
test/join_iterator_test.cxx

@@ -47,13 +47,6 @@ TEST(JoinIteratorTest, CanAccessChildIterator) {
   EXPECT_THAT(it.element_iterator(), end_aware_iterator(mv[0]));
 }
 
-TEST(JoinIteratorTest, EmptyConstructorEqualsEnd) {
-  std::vector<std::vector<int>> mv{{1, 2, 3}, {4, 5, 6}};
-  joining_iterator it(end_aware_iterator(mv.end(), mv.end()),
-                      end_aware_iterator(mv.back().end(), mv.back().end()));
-  EXPECT_THAT(it, decltype(it)());
-}
-
 TEST(JoinIteratorTest, PreIncrementAdvancesIterator) {
   std::vector<std::vector<int>> mv{{1, 2, 3}, {4, 5, 6}};
   joining_iterator it(mv);
@@ -73,22 +66,13 @@ TEST(JoinIteratorTest, PostIncrementReturnsCopyOfPrev) {
 TEST(JoinIteratorTest, MovesFromListToListWhenReachingEnd) {
   std::vector<std::vector<int>> mv{{1, 2, 3}, {4, 5, 6}};
   joining_iterator it(mv);
-  std::advance(it, 3);
+  std::advance(it, 2);
   EXPECT_THAT(*++it, mv[1][0]);
 }
 
 TEST(JoinIteratorTest, SkipsOverEmptyElements) {
   std::vector<std::vector<int>> mv{{1, 2, 3}, {}, {4, 5, 6}};
   joining_iterator it(mv);
-  std::advance(it, 3);
+  std::advance(it, 2);
   EXPECT_THAT(*++it, mv[2][0]);
 }
-
-TEST(JoinIteratorTest, IncrementEndIsUnsafe) {
-  std::vector<std::vector<int>> mv{{1, 2, 3}, {4, 5, 6}};
-  joining_iterator it(end_aware_iterator(mv.end(), mv.end()),
-                      end_aware_iterator(mv.back().end(), mv.back().end()));
-  joining_iterator const cp = it;
-  ++it;
-  EXPECT_NE(it, cp);
-}