Explorar o código

refactor: rebuild recursive_iterator and traits

Sam Jaffe hai 2 meses
pai
achega
f26ee848b9

+ 7 - 0
include/iterator/concepts.h

@@ -104,6 +104,13 @@ concept String = LegacyString<S> || StringViewCompat<S>;
 
 template <typename C>
 concept Range = (not String<C>) && std::ranges::range<C>;
+
+template <typename V>
+concept Assoc = std::is_const_v<typename V::first_type>;
+
+template <typename V>
+concept AssocRange = Assoc<V> && Range<typename V::second_type>;
+
 template <typename C>
 using iterator_t = decltype(std::begin(std::declval<C &>()));
 }

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

@@ -1,25 +0,0 @@
-#pragma once
-
-#include <iterator/concepts.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 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 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>>;
-}

+ 8 - 9
include/iterator/forwards.h

@@ -10,12 +10,6 @@
 #include <cstdlib>
 #include <iterator>
 
-namespace iterator::recursive {
-struct unbounded;
-template <size_t N, size_t I = 1> struct bounded;
-template <typename, typename = unbounded> class rimpl;
-}
-
 namespace iterator {
 struct sentinel_t;
 
@@ -26,9 +20,14 @@ template <typename OIt> class joining_iterator;
 template <typename It> class unkeyed_iterator;
 template <typename... Its> class zip_iterator;
 
-template <typename It> using recursive_iterator = recursive::rimpl<It>;
-template <typename It, std::size_t N>
-using recursive_iterator_n = recursive::rimpl<It, recursive::bounded<N>>;
+struct unbounded {};
+template <size_t N>
+  requires(N > 0)
+struct bounded {};
+
+template <typename It, typename MaxDepth = unbounded> class recursive_iterator;
+template <typename It, size_t N>
+using recursive_iterator_n = recursive_iterator<It, bounded<N>>;
 
 template <typename CRTP> class facade;
 

+ 128 - 138
include/iterator/recursive_iterator.h

@@ -7,220 +7,210 @@
 
 #pragma once
 
+#include <ranges>
 #include <string>
 #include <tuple>
 #include <utility>
 
-#include <iterator/detail/recursive_traits.h>
 #include <iterator/end_aware_iterator.h>
 #include <iterator/facade.h>
 #include <iterator/forwards.h>
 
 #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();
+namespace iterator {
+template <typename... Ts>
+using tuple_cat_t = decltype(std::tuple_cat(std::declval<Ts>()...));
+
+template <typename It, typename MaxDepth = unbounded, size_t N = 0,
+          typename V = std::iter_value_t<It>>
+struct tuple_expander {
+  using iterator_tuple = std::tuple<end_aware_iterator<It>>;
 };
 
-template <size_t N, size_t I> struct bounded {
-  template <typename It>
-  static constexpr recursion_type const 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;
+template <typename It, size_t N> struct tuple_expander<It, bounded<N + 1>, N> {
+  using iterator_tuple = std::tuple<end_aware_iterator<It>>;
 };
 
-template <typename It, typename Bnd = unbounded,
-          recursion_type = Bnd::template value<It>>
-struct tuple_expander;
+template <typename It, typename MaxDepth, size_t N, Range V>
+struct tuple_expander<It, MaxDepth, N, V> {
+  static It & _it;
 
-template <typename It, typename Bnd>
-struct tuple_expander<It, Bnd, recursion_type::END> {
-  using iter = std::tuple<end_aware_iterator<It>>;
-  decltype(auto) get(It iter) const {
-    if constexpr (associative_value<std::iter_value_t<It>>) {
-      return std::tie(iter->first, iter->second);
-    } else {
-      return std::tie(*iter);
-    }
-  }
-};
+  using next_iterator_t = decltype(std::begin(*_it));
+  using expand_next = tuple_expander<next_iterator_t, MaxDepth, N + 1>;
 
-template <typename... Ts>
-using tuple_cat_t = decltype(std::tuple_cat(VAL(Ts)...));
-
-template <typename It, typename Bnd>
-struct tuple_expander<It, Bnd, recursion_type::THRU> {
-  using next = decltype(std::begin(*VAL(It)));
-  using iter =
-      tuple_cat_t<std::tuple<end_aware_iterator<It>>,
-                  typename tuple_expander<next, typename Bnd::next>::iter>;
-  auto get(It) const { return std::make_tuple(); }
+  using iterator_tuple = tuple_cat_t<std::tuple<end_aware_iterator<It>>,
+                                     typename expand_next::iterator_tuple>;
 };
 
-template <typename It, typename Bnd>
-struct tuple_expander<It, Bnd, recursion_type::ASSOC> {
-  using next = decltype(std::begin(VAL(It)->second));
-  using iter =
-      tuple_cat_t<std::tuple<end_aware_iterator<It>>,
-                  typename tuple_expander<next, typename Bnd::next>::iter>;
-  auto get(It iter) const { return std::tie(iter->first); };
-};
+template <typename It, typename MaxDepth, size_t N, AssocRange V>
+struct tuple_expander<It, MaxDepth, N, V> {
+  static It & _it;
 
-/**
- * @brief An iterator type for nested collections, allowing you to treat it as
- * a single-layer collection.
- *
- * In order to provide a simple interface, if an associative container is used
- * in the chain, the type returned by operator*() is a tuple. If multiple
- * associative containers are nested, then the tuple will be of the form
- * std::tuple<key1, key2, ..., keyN, value>. To avoid copies, and allow
- * editting of underlying values, the tuple contains references.
- *
- * @tparam It The iterator type of the top-level collection.
- * @tparam Bnd The bounding type, representing how many layers this iterator
- * is willing to delve in the parent object.
- */
-template <typename It, typename Bnd>
-class rimpl : public facade<rimpl<It, Bnd>> {
-public:
-  using sentinel_type = sentinel_t;
-  using iters_t = typename tuple_expander<It, Bnd>::iter;
-  static constexpr size_t n_iters = std::tuple_size_v<iters_t>;
-  static constexpr size_t size = std::min(n_iters, Bnd::size);
+  using next_iterator_t = decltype(std::begin(_it->second));
+  using expand_next = tuple_expander<next_iterator_t, MaxDepth, N + 1>;
 
-private:
-  iters_t impl_;
+  using iterator_tuple = tuple_cat_t<std::tuple<end_aware_iterator<It>>,
+                                     typename expand_next::iterator_tuple>;
+};
 
+template <typename Tuple, typename Indices> class recursive_iterator_base;
+template <typename... It, size_t... Is>
+class recursive_iterator_base<std::tuple<It...>, std::index_sequence<Is...>>
+    : public std::tuple<It...> {
 public:
-  rimpl() = default;
-  rimpl(end_aware_iterator<It> iter) { assign<0>(iter); }
-  template <typename Ot>
-  rimpl(end_aware_iterator<Ot> other) : rimpl(end_aware_iterator<It>(other)) {}
-  template <typename Ot>
-  rimpl(rimpl<Ot, Bnd> other) : rimpl(end_aware_iterator<Ot>(other)) {}
+  static constexpr size_t LastIndex = sizeof...(It) - 1;
+  template <size_t I>
+  using iterator_type = std::tuple_element_t<I, std::tuple<It...>>;
+  template <size_t I> using value_type = std::iter_value_t<iterator_type<I>>;
 
+public:
   template <typename T> operator end_aware_iterator<T>() const {
-    return std::get<end_aware_iterator<T>>(impl_);
+    return std::get<end_aware_iterator<T>>(*this);
   }
 
   decltype(auto) dereference() const {
+    auto rval = std::tuple_cat(get<Is>()...);
     // Special Case Handling for circumstances where at least everything up to
     // the deepest nested container is non-associative. In this case, we don't
     // want to transmute our single element/association into a tuple, since
     // there's no benefit from that.
-    if constexpr (std::tuple_size_v<decltype(this->build_tuple())> == 1) {
-      return *std::get<size - 1>(impl_);
+    if constexpr (std::tuple_size_v<decltype(rval)> == 1) {
+      return std::get<0>(rval); // May be a reference
     } else {
-      return build_tuple();
+      return rval; // Tuple-of-references
     }
   }
 
-  void increment() { increment_i(); }
+  void increment() { increment<>(); }
 
-  bool at_end() const { return std::get<0>(impl_).at_end(); }
-  bool equal_to(rimpl const & other) const { return impl_ == other.impl_; }
+  bool at_end() const { return std::get<0>(*this).at_end(); }
+  bool equal_to(recursive_iterator_base const & other) const {
+    return *this == other;
+  }
 
-  // Used by std::get, don't use elsewhere...
-  auto const & impl() const { return impl_; }
+protected:
+  recursive_iterator_base() = default;
+  recursive_iterator_base(iterator_type<0> iter) { assign<0>(iter); }
 
 private:
-  template <size_t I = size - 1> bool increment_i() {
-    auto & iter = std::get<I>(impl_);
+  template <size_t I = LastIndex> bool increment() {
+    auto & iter = std::get<I>(*this);
     if (iter.at_end()) { return false; } // Make sure we don't go OOB
     ++iter;
     if constexpr (I > 0) {
-      while (iter.at_end() && increment_i<I - 1>()) {
-        assign<I>(*std::get<I - 1>(impl_));
+      while (iter.at_end() && increment<I - 1>()) {
+        assign<I>(*std::get<I - 1>(*this));
       }
     }
     return !iter.at_end();
   }
 
   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.
-    if constexpr (I == size - 1) {
-      return tuple_expander<decltype(it), unbounded, recursion_type::END>{}.get(
-          it);
+    auto iter = std::get<I>(*this);
+    if constexpr (I + 1 == sizeof...(It)) {
+      if constexpr (Assoc<value_type<I>>) {
+        return std::tie(iter->first, iter->second);
+      } else {
+        return std::tie(*iter);
+      }
+    } else if constexpr (Assoc<value_type<I>>) {
+      return std::tie(iter->first);
     } else {
-      return tuple_expander<decltype(it)>{}.get(it);
+      return std::make_tuple();
     }
   }
 
-  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) {
+  template <size_t I, typename T> void assign(end_aware_iterator<T> it) {
+    std::get<I>(*this) = it;
+    if constexpr (I < LastIndex) {
       if (!it.at_end()) { assign<I + 1>(*it); }
     }
   }
 
-  template <size_t I, typename C> void assign(C && collection) {
-    assign<I>(end_aware_iterator(std::forward<C>(collection)));
+  template <size_t I, typename T> void assign(T && value) {
+    if constexpr (Range<T>) {
+      assign<I>(end_aware_iterator(std::forward<T>(value)));
+    } else {
+      assign<I>(value.second);
+    }
   }
+};
 
-  template <size_t I, typename K, typename V>
-  void assign(std::pair<K const, V> const & pair) {
-    assign<I>(pair.second);
-  }
-  template <size_t I, typename K, typename V>
-  void assign(std::pair<K const, V> & pair) {
-    assign<I>(pair.second);
-  }
+template <typename It, typename MaxDepth> struct recursive_iterator_helper {
+  using iterator_tuple = typename tuple_expander<It, MaxDepth>::iterator_tuple;
+
+  static constexpr auto extent = std::tuple_size_v<iterator_tuple>;
+  using indices = decltype(std::make_index_sequence<extent>());
+
+  using type = recursive_iterator_base<iterator_tuple, indices>;
 };
-}
 
-namespace std {
-template <std::size_t I, typename It>
-auto get(::iterator::recursive_iterator<It> const & iter) {
-  return ::std::get<I>(iter.impl());
-}
+/**
+ * @brief An iterator type for nested collections, allowing you to treat it as
+ * a single-layer collection.
+ *
+ * In order to provide a simple interface, if an associative container is used
+ * in the chain, the type returned by operator*() is a tuple. If multiple
+ * associative containers are nested, then the tuple will be of the form
+ * std::tuple<key1, key2, ..., keyN, value>. To avoid copies, and allow
+ * editting of underlying values, the tuple contains references.
+ *
+ * @tparam It The iterator type of the top-level collection.
+ * @tparam MaxDepth The bounding type, representing how many layers this
+ * iterator is willing to delve in the parent object.
+ */
+template <typename It, typename MaxDepth>
+class recursive_iterator : public recursive_iterator_helper<It, MaxDepth>::type,
+                           public facade<recursive_iterator<It, MaxDepth>> {
+public:
+  using sentinel_type = sentinel_t;
 
-template <std::size_t I, typename It, std::size_t N>
-auto get(::iterator::recursive_iterator_n<It, N> const & iter) {
-  static_assert(I < N, "Cannot get past bounding level");
-  return ::std::get<I>(iter.impl());
-}
-}
+public:
+  recursive_iterator() = default;
+
+  explicit recursive_iterator(Range auto & range, MaxDepth = {})
+      : recursive_iterator(end_aware_iterator(range)) {}
 
-template <typename C> auto make_recursive_iterator(C && collect) {
-  return iterator::recursive_iterator<iterator::iterator_t<C>>(collect);
+  explicit recursive_iterator(end_aware_iterator<It> iter, MaxDepth = {})
+      : recursive_iterator::recursive_iterator_base(iter) {}
+
+  template <typename Ot>
+  explicit recursive_iterator(end_aware_iterator<Ot> other, MaxDepth = {})
+      : recursive_iterator(end_aware_iterator<It>(other)) {}
+
+  template <typename Ot>
+  explicit recursive_iterator(recursive_iterator<Ot, MaxDepth> other)
+      : recursive_iterator(end_aware_iterator<Ot>(other)) {}
+};
+
+template <typename Range, typename MaxDepth>
+recursive_iterator(Range &, MaxDepth)
+    -> recursive_iterator<iterator_t<Range>, MaxDepth>;
+template <typename Range>
+recursive_iterator(Range &) -> recursive_iterator<iterator_t<Range>, unbounded>;
 }
 
-template <std::size_t Max, typename C>
-auto make_recursive_iterator(C && collect) {
-  return iterator::recursive_iterator_n<iterator::iterator_t<C>, Max>(collect);
+namespace std {
+template <size_t I, typename It, typename MaxDepth>
+auto get(::iterator::recursive_iterator<It, MaxDepth> const & iter) {
+  using return_type = std::decay_t<decltype(iter)>::template iterator_type<I>;
+  return static_cast<return_type>(iter);
+}
 }
 
 namespace iterator::views {
 template <size_t N>
 struct recursive_n_fn : std::ranges::range_adaptor_closure<recursive_n_fn<N>> {
   template <std::ranges::range Rng> auto operator()(Rng && rng) const {
-    auto begin =
-        make_recursive_iterator<N>(std::views::all(std::forward<Rng>(rng)));
+    auto begin = recursive_iterator(std::forward<Rng>(rng), bounded<N>{});
     return std::ranges::subrange(begin, decltype(begin)());
   }
 };
 
 struct recursive_fn : std::ranges::range_adaptor_closure<recursive_fn> {
   template <std::ranges::range Rng> auto operator()(Rng && rng) const {
-    auto begin =
-        make_recursive_iterator(std::views::all(std::forward<Rng>(rng)));
+    auto begin = recursive_iterator(std::forward<Rng>(rng));
     return std::ranges::subrange(begin, decltype(begin)());
   }
 };

+ 1 - 1
include/iterator/unkeyed_iterator.h

@@ -20,7 +20,7 @@ namespace iterator {
  * have something crazy like a four-level map and then do:
  * \code
  * std::map<int, std::map<std::string, std::map<int, BigType>>> object;
- * auto const rit = make_recursive_iterator(object);
+ * auto const rit = recursive_iterator(object);
  * for (unkeyed_iterator<decltype(rit)> it = rit, end = {}; it != end; ++it) {
  *   // Process only BigType, discarding all of the keys that we need to walk
  * }

+ 0 - 4
iterator.xcodeproj/project.pbxproj

@@ -14,7 +14,6 @@
 		CD41AFE72E7F13E4004F3E51 /* sentinel.h in Headers */ = {isa = PBXBuildFile; fileRef = CD5A8E7329D7910D008C2A4F /* sentinel.h */; };
 		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 */; };
 		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 */; };
@@ -93,7 +92,6 @@
 		CDA2B6142858128C004D5353 /* indexed_iterator.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = indexed_iterator.h; sourceTree = "<group>"; };
 		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>"; };
 		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>"; };
@@ -213,7 +211,6 @@
 			children = (
 				CDA2B61A2858128C004D5353 /* arrow_proxy.h */,
 				CD5AEB3129D8885400A390A4 /* macro.h */,
-				CDA2B6182858128C004D5353 /* recursive_traits.h */,
 				CD5AEB3229D8886200A390A4 /* undef.h */,
 			);
 			path = detail;
@@ -260,7 +257,6 @@
 				CD41AFE72E7F13E4004F3E51 /* sentinel.h in Headers */,
 				CD41AFE82E7F13E4004F3E51 /* arrow_proxy.h in Headers */,
 				CD41AFE92E7F13E4004F3E51 /* macro.h in Headers */,
-				CD41AFEA2E7F13E4004F3E51 /* recursive_traits.h in Headers */,
 				CD41AFEC2E7F13E4004F3E51 /* undef.h in Headers */,
 				CD41AFED2E7F13E4004F3E51 /* capture_iterator.h in Headers */,
 				CD41AFEE2E7F13E4004F3E51 /* end_aware_iterator.h in Headers */,

+ 16 - 14
test/recursive_iterator_accessors_test.cxx

@@ -8,32 +8,34 @@
 #include "ranges.h"
 #include "xcode_gtest_helper.h"
 
+using iterator::bounded;
 using iterator::end_aware_iterator;
+using iterator::recursive_iterator;
 
 using testing::StaticAssertTypeEq;
 
 TEST(RecursiveIteratorTest, DoesNotUnwrapString) {
   std::vector<std::string> obj{"A", "B", "C", "D"};
-  auto rit = make_recursive_iterator(obj);
+  auto rit = recursive_iterator(obj);
   StaticAssertTypeEq<decltype(rit.operator->()), std::string *>();
 }
 
 TEST(RecursiveIteratorTest, CanArrowMultiVector) {
   std::vector<std::vector<int>> obj{{{0, 1}}, {{2, 3}}};
-  auto rit = make_recursive_iterator(obj);
+  auto rit = recursive_iterator(obj);
   StaticAssertTypeEq<decltype(rit.operator->()), int *>();
   EXPECT_EQ(rit.operator->(), &obj[0][0]);
 }
 
 // TEST(RecursiveIteratorTest, CannotArrowMap) {
 //  std::map<int, std::vector<int>> obj{{1, {{0, 1}}}, {2, {{2, 3}}}};
-//  auto rit = make_recursive_iterator(obj);
+//  auto rit = recursive_iterator(obj);
 //  StaticAssertTypeEq<decltype(rit.operator->()), void>();
 //}
 
 TEST(RecursiveIteratorTest, CanAccessOuterterator) {
   std::map<int, std::vector<int>> obj{{1, {{0, 1}}}, {2, {{2, 3}}}};
-  auto rit = make_recursive_iterator(obj);
+  auto rit = recursive_iterator(obj);
 
   end_aware_iterator<decltype(obj)::iterator> inner = rit;
   EXPECT_EQ(&std::get<0>(*rit), &(inner->first));
@@ -41,7 +43,7 @@ TEST(RecursiveIteratorTest, CanAccessOuterterator) {
 
 TEST(RecursiveIteratorTest, CanAccessInnerIterator) {
   std::map<int, std::vector<int>> obj{{1, {{0, 1}}}, {2, {{2, 3}}}};
-  auto rit = make_recursive_iterator(obj);
+  auto rit = recursive_iterator(obj);
 
   end_aware_iterator<std::vector<int>::iterator> inner = rit;
   EXPECT_EQ(&std::get<1>(*rit), &*inner);
@@ -52,7 +54,7 @@ TEST(RecursiveIteratorTest, CanStdGetToAllLayersOfInternalIteration) {
       {1, {{{1, 1}}, {{2, 2}}}}, // 2 1-element maps
       {2, {{{3, 3}, {4, 4}}}}    // 1 2-element map
   };
-  auto rit = make_recursive_iterator(obj);
+  auto rit = recursive_iterator(obj);
   using mvm_iterator = std::map<int, std::vector<std::map<int, int>>>::iterator;
   StaticAssertTypeEq<decltype(std::get<0>(rit)),
                      end_aware_iterator<mvm_iterator>>();
@@ -71,7 +73,7 @@ TEST(RecursiveIteratorTest, CanAccessInternalIteratorsWithGet) {
       {1, {{{1, 1}}, {{2, 2}}}}, // 2 1-element maps
       {2, {{{3, 3}, {4, 4}}}}    // 1 2-element map
   };
-  auto rit = make_recursive_iterator(obj);
+  auto rit = recursive_iterator(obj);
   EXPECT_EQ(std::get<0>(rit), end_aware_iterator(obj));
   EXPECT_EQ(std::get<1>(rit), end_aware_iterator(obj[1]));
   EXPECT_EQ(std::get<2>(rit), end_aware_iterator(obj[1][0]));
@@ -83,7 +85,7 @@ TEST(RecursiveIteratorTest, CanCastCompatibleIterators) {
       {1, {{{1, 1}}, {{2, 2}}}}, // 2 1-element maps
       {2, {{{3, 3}, {4, 4}}}}    // 1 2-element map
   };
-  auto rit = make_recursive_iterator(obj);
+  auto rit = recursive_iterator(obj);
   iterator::recursive_iterator<decltype(obj)::const_iterator> cit(rit);
 }
 
@@ -92,7 +94,7 @@ TEST(RecursiveIteratorTest, EmptyCtorIsEnd) {
       {1, {{{1, 1}}, {{2, 2}}}}, // 2 1-element maps
       {2, {{{3, 3}, {4, 4}}}}    // 1 2-element map
   };
-  auto rit = make_recursive_iterator(obj);
+  auto rit = recursive_iterator(obj);
 
   EXPECT_NE(rit, iterator::sentinel);
   EXPECT_EQ(ranges::distance(rit, iterator::sentinel), 4);
@@ -106,7 +108,7 @@ TEST(BoundedRecursiveIteratorTest, CanStdGetToNLayersOfInternalIteration) {
       {1, {{{1, 1}}, {{2, 2}}}}, // 2 1-element maps
       {2, {{{3, 3}, {4, 4}}}}    // 1 2-element map
   };
-  auto rit = make_recursive_iterator<2>(obj);
+  auto rit = recursive_iterator(obj, bounded<2>{});
   using mvm_iterator = std::map<int, std::vector<std::map<int, int>>>::iterator;
   StaticAssertTypeEq<decltype(std::get<0>(rit)),
                      end_aware_iterator<mvm_iterator>>();
@@ -122,7 +124,7 @@ TEST(BoundedRecursiveIteratorTest, CanAccessInternalIteratorsWithGet) {
       {1, {{{1, 1}}, {{2, 2}}}}, // 2 1-element maps
       {2, {{{3, 3}, {4, 4}}}}    // 1 2-element map
   };
-  auto rit = make_recursive_iterator<2>(obj);
+  auto rit = recursive_iterator(obj, bounded<2>{});
   EXPECT_EQ(std::get<0>(rit), end_aware_iterator(obj));
   EXPECT_EQ(std::get<1>(rit), end_aware_iterator(obj[1]));
 }
@@ -133,7 +135,7 @@ TEST(BoundedRecursiveIteratorTest, CanCastCompatibleIterators) {
       {1, {{{1, 1}}, {{2, 2}}}}, // 2 1-element maps
       {2, {{{3, 3}, {4, 4}}}}    // 1 2-element map
   };
-  auto rit = make_recursive_iterator<2>(obj);
+  auto rit = recursive_iterator(obj, bounded<2>{});
   iterator::recursive_iterator_n<decltype(obj)::const_iterator, 2> cit(rit);
 }
 
@@ -142,7 +144,7 @@ TEST(BoundedRecursiveIteratorTest, EmptyCtorIsEnd) {
       {1, {{{1, 1}}, {{2, 2}}}}, // 2 1-element maps
       {2, {{{3, 3}, {4, 4}}}}    // 1 2-element map
   };
-  auto rit = make_recursive_iterator<3>(obj);
+  auto rit = recursive_iterator(obj, bounded<3>{});
   EXPECT_NE(rit, iterator::sentinel);
   EXPECT_EQ(ranges::distance(rit, iterator::sentinel), 4);
 
@@ -155,6 +157,6 @@ TEST(BoundedRecursiveIteratorTest, CanFetchInnerCollections) {
       {{{{1, 1}}, {{2, 2}}}}, // 2 1-element maps
       {{{{3, 3}, {4, 4}}}}    // 1 2-element map
   };
-  auto rit = make_recursive_iterator<2>(obj);
+  auto rit = recursive_iterator(obj, bounded<2>{});
   EXPECT_EQ(*rit, obj[0][0]);
 }

+ 14 - 9
test/recursive_iterator_map_test.cxx

@@ -5,15 +5,20 @@
 #include <tuple>
 #include <vector>
 
+#include <iterator/forwards.h>
+
 #include "ranges.h"
 #include "xcode_gtest_helper.h"
 
+using iterator::bounded;
+using iterator::recursive_iterator;
+
 using testing::IsEmpty;
 
 TEST(RecursiveIteratorMapTest, PreIncrementAdvancesIterator) {
   std::map<int, std::map<int, std::map<int, int>>> const map{
       {1, {{1, {{1, 1}}}}}, {2, {{2, {{2, 2}}}, {3, {{3, 3}, {4, 4}}}}}};
-  auto rit = make_recursive_iterator(map);
+  auto rit = recursive_iterator(map);
   EXPECT_EQ(std::get<3>(*rit), 1);
   EXPECT_EQ(std::get<3>(*++rit), 2);
   EXPECT_EQ(std::get<3>(*rit), 2);
@@ -22,7 +27,7 @@ TEST(RecursiveIteratorMapTest, PreIncrementAdvancesIterator) {
 TEST(RecursiveIteratorMapTest, PostIncrementReturnsCopyOfPrev) {
   std::map<int, std::map<int, std::map<int, int>>> const map{
       {1, {{1, {{1, 1}}}}}, {2, {{2, {{2, 2}}}, {3, {{3, 3}, {4, 4}}}}}};
-  auto rit = make_recursive_iterator(map);
+  auto rit = recursive_iterator(map);
   EXPECT_EQ(std::get<3>(*rit), 1);
   EXPECT_EQ(std::get<3>(*rit++), 1);
   EXPECT_EQ(std::get<3>(*rit), 2);
@@ -31,7 +36,7 @@ TEST(RecursiveIteratorMapTest, PostIncrementReturnsCopyOfPrev) {
 TEST(RecursiveIteratorMapTest, IterDistanceIsSumOfInnerContainerSizes) {
   std::map<int, std::map<int, std::map<int, int>>> const map{
       {1, {{1, {{1, 1}}}}}, {2, {{2, {{2, 2}}}, {3, {{3, 3}, {4, 4}}}}}};
-  auto rit = make_recursive_iterator(map);
+  auto rit = recursive_iterator(map);
 
   EXPECT_EQ(ranges::distance(rit, iterator::sentinel), 4);
 }
@@ -41,7 +46,7 @@ TEST(RecursiveIteratorMapTest, ElementsAreUnwrappedAsATuple) {
       {1, {{1, {{1, 1}}}}}, {2, {{2, {{2, 2}}}, {3, {{3, 3}, {4, 4}}}}}};
   std::vector<std::tuple<int, int, int, int>> const expected{
       {1, 1, 1, 1}, {2, 2, 2, 2}, {2, 3, 3, 3}, {2, 3, 4, 4}};
-  auto rit = make_recursive_iterator(map);
+  auto rit = recursive_iterator(map);
 
   EXPECT_EQ((ranges::to<std::vector<std::tuple<int, int, int, int>>>(
                 rit, iterator::sentinel)),
@@ -51,7 +56,7 @@ TEST(RecursiveIteratorMapTest, ElementsAreUnwrappedAsATuple) {
 TEST(RecursiveIteratorMapTest, CanMutatePointedToData) {
   std::map<int, std::map<int, std::map<int, int>>> map{
       {1, {{1, {{1, 1}}}}}, {2, {{2, {{2, 2}}}, {3, {{3, 3}, {4, 4}}}}}};
-  auto rit = make_recursive_iterator(map);
+  auto rit = recursive_iterator(map);
   std::get<3>(*rit) = 4;
   EXPECT_EQ(map[1][1][1], 4);
 }
@@ -59,7 +64,7 @@ TEST(RecursiveIteratorMapTest, CanMutatePointedToData) {
 TEST(BoundRecursiveIteratorMapTest, PreIncrementAdvancesIterator) {
   std::map<int, std::map<int, std::map<int, int>>> map{
       {1, {{1, {{1, 1}}}}}, {2, {{2, {{2, 2}}}, {3, {{3, 3}, {4, 4}}}}}};
-  auto rit = make_recursive_iterator<2>(map);
+  auto rit = recursive_iterator(map, bounded<2>{});
   EXPECT_EQ(std::get<2>(*rit), map[1][1]);
   EXPECT_EQ(std::get<2>(*++rit), map[2][2]);
   EXPECT_EQ(std::get<2>(*rit), map[2][2]);
@@ -68,7 +73,7 @@ TEST(BoundRecursiveIteratorMapTest, PreIncrementAdvancesIterator) {
 TEST(BoundRecursiveIteratorMapTest, PostIncrementReturnsCopyOfPrev) {
   std::map<int, std::map<int, std::map<int, int>>> map{
       {1, {{1, {{1, 1}}}}}, {2, {{2, {{2, 2}}}, {3, {{3, 3}, {4, 4}}}}}};
-  auto rit = make_recursive_iterator<2>(map);
+  auto rit = recursive_iterator(map, bounded<2>{});
   EXPECT_EQ(std::get<2>(*rit), map[1][1]);
   EXPECT_EQ(std::get<2>(*rit++), map[1][1]);
   EXPECT_EQ(std::get<2>(*rit), map[2][2]);
@@ -77,7 +82,7 @@ TEST(BoundRecursiveIteratorMapTest, PostIncrementReturnsCopyOfPrev) {
 TEST(BoundRecursiveIteratorMapTest, IterDistanceSumOnNLayersSize) {
   std::map<int, std::map<int, std::map<int, int>>> const map{
       {1, {{1, {{1, 1}}}}}, {2, {{2, {{2, 2}}}, {3, {{3, 3}, {4, 4}}}}}};
-  auto rit = make_recursive_iterator<2>(map);
+  auto rit = recursive_iterator(map, bounded<2>{});
 
   EXPECT_EQ(ranges::distance(rit, iterator::sentinel), 3);
 }
@@ -96,7 +101,7 @@ TEST(BoundRecursiveIteratorMapTest, ElementsAreUnwrappedAsATuple) {
 TEST(BoundedRecursiveIteratorMapTest, CanMutatePointedToData) {
   std::map<int, std::map<int, std::map<int, int>>> map{
       {1, {{1, {{1, 1}}}}}, {2, {{2, {{2, 2}}}, {3, {{3, 3}, {4, 4}}}}}};
-  auto rit = make_recursive_iterator<2>(map);
+  auto rit = recursive_iterator(map, bounded<2>{});
   std::get<2>(*rit).clear();
   EXPECT_THAT(map[1][1], IsEmpty());
 }

+ 15 - 13
test/recursive_iterator_mixed_container_test.cxx

@@ -6,9 +6,11 @@
 #include "ranges.h"
 #include "xcode_gtest_helper.h"
 
+using iterator::recursive_iterator;
+
 TEST(RecursiveIteratorMapVectorTest, IterDistanceIsSumOfInnerContainerSizes) {
   std::map<int, std::vector<int>> const obj{{1, {1, 2}}, {2, {3, 4, 5}}};
-  auto rit = make_recursive_iterator(obj);
+  auto rit = recursive_iterator(obj);
 
   EXPECT_EQ(ranges::distance(rit, iterator::sentinel), 5);
 }
@@ -17,7 +19,7 @@ TEST(RecursiveIteratorMapVectorTest, ElementsAreUnwrappedAsATuple) {
   std::map<int, std::vector<int>> const obj{{1, {1, 2}}, {2, {3, 4, 5}}};
   std::vector<std::tuple<int, int>> const expected{
       {1, 1}, {1, 2}, {2, 3}, {2, 4}, {2, 5}};
-  auto rit = make_recursive_iterator(obj);
+  auto rit = recursive_iterator(obj);
 
   EXPECT_EQ(
       (ranges::to<std::vector<std::tuple<int, int>>>(rit, iterator::sentinel)),
@@ -26,7 +28,7 @@ TEST(RecursiveIteratorMapVectorTest, ElementsAreUnwrappedAsATuple) {
 
 TEST(RecursiveIteratorMapVectorTest, CanMutatePointedToData) {
   std::map<int, std::vector<int>> obj{{1, {1, 2}}, {2, {3, 4, 5}}};
-  auto rit = make_recursive_iterator(obj);
+  auto rit = recursive_iterator(obj);
   std::get<1>(*rit) = 6;
   EXPECT_EQ(obj[1][0], 6);
 }
@@ -34,7 +36,7 @@ TEST(RecursiveIteratorMapVectorTest, CanMutatePointedToData) {
 TEST(RecursiveIteratorMapMapVectorTest, CanMutatePointedToData) {
   std::map<int, std::map<int, std::vector<int>>> obj{{1, {{1, {1, 2}}}},
                                                      {2, {{1, {3, 4, 5}}}}};
-  auto rit = make_recursive_iterator(obj);
+  auto rit = recursive_iterator(obj);
   std::get<2>(*rit) = 6;
   EXPECT_EQ(obj[1][1][0], 6);
 }
@@ -42,7 +44,7 @@ TEST(RecursiveIteratorMapMapVectorTest, CanMutatePointedToData) {
 TEST(RecursiveIteratorVectorMapTest, IterDistanceIsSumOfInnerContainerSizes) {
   std::vector<std::map<int, int>> const obj{{{1, 1}, {2, 2}},
                                             {{3, 3}, {4, 4}, {5, 5}}};
-  auto rit = make_recursive_iterator(obj);
+  auto rit = recursive_iterator(obj);
 
   EXPECT_EQ(ranges::distance(rit, iterator::sentinel), 5);
 }
@@ -52,7 +54,7 @@ TEST(RecursiveIteratorVectorMapTest, ElementsAreUnwrappedAsATuple) {
                                             {{3, 3}, {4, 4}, {5, 5}}};
   std::vector<std::pair<int, int>> const expected{
       {1, 1}, {2, 2}, {3, 3}, {4, 4}, {5, 5}};
-  auto rit = make_recursive_iterator(obj);
+  auto rit = recursive_iterator(obj);
 
   EXPECT_EQ(
       (ranges::to<std::vector<std::pair<int, int>>>(rit, iterator::sentinel)),
@@ -62,7 +64,7 @@ TEST(RecursiveIteratorVectorMapTest, ElementsAreUnwrappedAsATuple) {
 TEST(RecursiveIteratorVectorMapTest, CanMutatePointedToData) {
   std::vector<std::map<int, int>> obj{{{1, 1}, {2, 2}},
                                       {{3, 3}, {4, 4}, {5, 5}}};
-  auto rit = make_recursive_iterator(obj);
+  auto rit = recursive_iterator(obj);
   std::get<1>(*rit) = 6;
   EXPECT_EQ(obj[0][1], 6);
 }
@@ -71,7 +73,7 @@ TEST(RecursiveIteratorMapVecMapTest, IterDistanceIsSumOfInnerContainerSizes) {
   std::map<int, std::vector<std::map<int, int>>> const obj{
       {1, {{{1, 1}, {2, 2}}}}};
   std::vector<std::tuple<int, int, int>> const expected{{1, 1, 1}, {1, 2, 2}};
-  auto rit = make_recursive_iterator(obj);
+  auto rit = recursive_iterator(obj);
 
   EXPECT_EQ(ranges::distance(rit, iterator::sentinel), expected.size());
 }
@@ -80,7 +82,7 @@ TEST(RecursiveIteratorMapVecMapTest, ElementsAreUnwrappedAsATuple) {
   std::map<int, std::vector<std::map<int, int>>> const obj{
       {1, {{{1, 1}, {2, 2}}}}};
   std::vector<std::tuple<int, int, int>> const expected{{1, 1, 1}, {1, 2, 2}};
-  auto rit = make_recursive_iterator(obj);
+  auto rit = recursive_iterator(obj);
 
   EXPECT_EQ((ranges::to<std::vector<std::tuple<int, int, int>>>(
                 rit, iterator::sentinel)),
@@ -89,7 +91,7 @@ TEST(RecursiveIteratorMapVecMapTest, ElementsAreUnwrappedAsATuple) {
 
 TEST(RecursiveIteratorMapVecMapTest, CanMutatePointedToData) {
   std::map<int, std::vector<std::map<int, int>>> obj{{1, {{{1, 1}, {2, 2}}}}};
-  auto rit = make_recursive_iterator(obj);
+  auto rit = recursive_iterator(obj);
   std::get<2>(*rit) = 4;
   EXPECT_EQ(obj[1][0][1], 4);
 }
@@ -97,7 +99,7 @@ TEST(RecursiveIteratorMapVecMapTest, CanMutatePointedToData) {
 TEST(RecursiveIteratorVecMapVecTest, IterDistanceIsSumOfInnerContainerSizes) {
   std::vector<std::map<int, std::vector<int>>> const obj{
       {{1, {1, 2}}, {2, {3, 4, 5}}}, {{1, {3, 4}}}};
-  auto rit = make_recursive_iterator(obj);
+  auto rit = recursive_iterator(obj);
 
   EXPECT_EQ(ranges::distance(rit, iterator::sentinel), 7);
 }
@@ -107,7 +109,7 @@ TEST(RecursiveIteratorVecMapVecTest, ElementsAreUnwrappedAsATuple) {
       {{1, {1, 2}}, {2, {3, 4, 5}}}, {{1, {3, 4}}}};
   std::vector<std::tuple<int, int>> const expected{
       {1, 1}, {1, 2}, {2, 3}, {2, 4}, {2, 5}, {1, 3}, {1, 4}};
-  auto rit = make_recursive_iterator(obj);
+  auto rit = recursive_iterator(obj);
 
   EXPECT_EQ(
       (ranges::to<std::vector<std::tuple<int, int>>>(rit, iterator::sentinel)),
@@ -117,7 +119,7 @@ TEST(RecursiveIteratorVecMapVecTest, ElementsAreUnwrappedAsATuple) {
 TEST(RecursiveIteratorVecMapVecTest, CanMutatePointedToData) {
   std::vector<std::map<int, std::vector<int>>> obj{
       {{1, {1, 2}}, {2, {3, 4, 5}}}, {{1, {3, 4}}}};
-  auto rit = make_recursive_iterator(obj);
+  auto rit = recursive_iterator(obj);
   std::get<1>(*rit) = 6;
   EXPECT_EQ(obj[0][1][0], 6);
 }

+ 8 - 6
test/recursive_iterator_single_level_test.cxx

@@ -14,44 +14,46 @@
 #include "ranges.h"
 #include "xcode_gtest_helper.h"
 
+using iterator::recursive_iterator;
+
 TEST(RecursiveIteratorSingleVectorTest, IterDistanceIsContainerSize) {
   std::vector<int> const vec{1, 2, 3, 4, 5};
-  auto rit = make_recursive_iterator(vec);
+  auto rit = recursive_iterator(vec);
 
   EXPECT_THAT(ranges::distance(rit, iterator::sentinel), vec.size());
 }
 
 TEST(RecursiveIteratorSingleVectorTest, DataMatchesContainerIterator) {
   std::vector<int> const vec{1, 2, 3, 4, 5};
-  auto rit = make_recursive_iterator(vec);
+  auto rit = recursive_iterator(vec);
 
   EXPECT_THAT(ranges::to<std::vector<int>>(rit, iterator::sentinel), vec);
 }
 
 TEST(RecursiveIteratorSingleVectorTest, CanMutatePointedToData) {
   std::vector<int> vec{1, 2, 3, 4, 5};
-  auto rit = make_recursive_iterator(vec);
+  auto rit = recursive_iterator(vec);
   *rit = 6;
   EXPECT_THAT(vec[0], 6);
 }
 
 TEST(RecursiveIteratorSingleMapTest, IterDistanceIsContainerSize) {
   std::map<int, int> const map{{1, 1}, {2, 2}, {3, 3}};
-  auto rit = make_recursive_iterator(map);
+  auto rit = recursive_iterator(map);
 
   EXPECT_THAT(ranges::distance(rit, iterator::sentinel), map.size());
 }
 
 TEST(RecursiveIteratorSingleMapTest, DataMatchesContainerIterator) {
   std::map<int, int> const map{{1, 1}, {2, 2}, {3, 3}};
-  auto rit = make_recursive_iterator(map);
+  auto rit = recursive_iterator(map);
 
   EXPECT_THAT((ranges::to<std::map<int, int>>(rit, iterator::sentinel)), map);
 }
 
 TEST(RecursiveIteratorSingleMapTest, CanMutatePointedToData) {
   std::map<int, int> map{{1, 1}, {2, 2}, {3, 3}};
-  auto rit = make_recursive_iterator(map);
+  auto rit = recursive_iterator(map);
   std::get<1>(*rit) = 4;
   EXPECT_THAT(map[1], 4);
 }

+ 15 - 10
test/recursive_iterator_vector_test.cxx

@@ -2,14 +2,19 @@
 
 #include <vector>
 
+#include <iterator/forwards.h>
+
 #include "ranges.h"
 #include "xcode_gtest_helper.h"
 
+using iterator::bounded;
+using iterator::recursive_iterator;
+
 using testing::IsEmpty;
 
 TEST(RecursiveIteratorVecTest, PreIncrementAdvancesIterator) {
   std::vector<std::vector<std::vector<int>>> const vec{{{1, 2}}, {{3}, {4, 5}}};
-  auto rit = make_recursive_iterator(vec);
+  auto rit = recursive_iterator(vec);
   EXPECT_THAT(*rit, 1);
   EXPECT_THAT(*++rit, 2);
   EXPECT_THAT(*rit, 2);
@@ -17,7 +22,7 @@ TEST(RecursiveIteratorVecTest, PreIncrementAdvancesIterator) {
 
 TEST(RecursiveIteratorVecTest, PostIncrementReturnsCopyOfPrev) {
   std::vector<std::vector<std::vector<int>>> const vec{{{1, 2}}, {{3}, {4, 5}}};
-  auto rit = make_recursive_iterator(vec);
+  auto rit = recursive_iterator(vec);
   EXPECT_THAT(*rit, 1);
   EXPECT_THAT(*rit++, 1);
   EXPECT_THAT(*rit, 2);
@@ -25,14 +30,14 @@ TEST(RecursiveIteratorVecTest, PostIncrementReturnsCopyOfPrev) {
 
 TEST(RecursiveIteratorVecTest, IterDistanceIsSumOfInnerContainerSizes) {
   std::vector<std::vector<std::vector<int>>> const vec{{{1, 2}}, {{3}, {4, 5}}};
-  auto rit = make_recursive_iterator(vec);
+  auto rit = recursive_iterator(vec);
 
   EXPECT_THAT(ranges::distance(rit, iterator::sentinel), 5);
 }
 
 TEST(RecursiveIteratorVecTest, FlattensVectorDataLikeJoinIterator) {
   std::vector<std::vector<std::vector<int>>> const vec{{{1, 2}}, {{3}, {4, 5}}};
-  auto rit = make_recursive_iterator(vec);
+  auto rit = recursive_iterator(vec);
 
   std::vector<int> const expected{1, 2, 3, 4, 5};
   EXPECT_THAT(ranges::to<std::vector<int>>(rit, iterator::sentinel), expected);
@@ -40,14 +45,14 @@ TEST(RecursiveIteratorVecTest, FlattensVectorDataLikeJoinIterator) {
 
 TEST(RecursiveIteratorVecTest, CanMutatePointedToData) {
   std::vector<std::vector<std::vector<int>>> vec{{{1, 2}}, {{3}, {4, 5}}};
-  auto rit = make_recursive_iterator(vec);
+  auto rit = recursive_iterator(vec);
   *rit = 6;
   EXPECT_THAT(vec[0][0][0], 6);
 }
 
 TEST(BoundedRecursiveIteratorVecTest, PreIncrementAdvancesIterator) {
   std::vector<std::vector<std::vector<int>>> const vec{{{1, 2}}, {{3}, {4, 5}}};
-  auto rit = make_recursive_iterator<2>(vec);
+  auto rit = recursive_iterator(vec, bounded<2>{});
   EXPECT_THAT(*rit, vec[0][0]);
   EXPECT_THAT(*++rit, vec[1][0]);
   EXPECT_THAT(*rit, vec[1][0]);
@@ -55,7 +60,7 @@ TEST(BoundedRecursiveIteratorVecTest, PreIncrementAdvancesIterator) {
 
 TEST(BoundedRecursiveIteratorVecTest, PostIncrementReturnsCopyOfPrev) {
   std::vector<std::vector<std::vector<int>>> const vec{{{1, 2}}, {{3}, {4, 5}}};
-  auto rit = make_recursive_iterator<2>(vec);
+  auto rit = recursive_iterator(vec, bounded<2>{});
   EXPECT_THAT(*rit, vec[0][0]);
   EXPECT_THAT(*rit++, vec[0][0]);
   EXPECT_THAT(*rit, vec[1][0]);
@@ -63,14 +68,14 @@ TEST(BoundedRecursiveIteratorVecTest, PostIncrementReturnsCopyOfPrev) {
 
 TEST(BoundedRecursiveIteratorVecTest, IterDistanceSumOnNLayersSize) {
   std::vector<std::vector<std::vector<int>>> const vec{{{1, 2}}, {{3}, {4, 5}}};
-  auto rit = make_recursive_iterator<2>(vec);
+  auto rit = recursive_iterator(vec, bounded<2>{});
 
   EXPECT_THAT(ranges::distance(rit, iterator::sentinel), 3);
 }
 
 TEST(BoundedRecursiveIteratorVecTest, ElementsAreUnwrappedAsATuple) {
   std::vector<std::vector<std::vector<int>>> const vec{{{1, 2}}, {{3}, {4, 5}}};
-  auto rit = make_recursive_iterator<2>(vec);
+  auto rit = recursive_iterator(vec, bounded<2>{});
 
   std::vector<std::vector<int>> const expected{{1, 2}, {3}, {4, 5}};
   EXPECT_THAT(
@@ -80,7 +85,7 @@ TEST(BoundedRecursiveIteratorVecTest, ElementsAreUnwrappedAsATuple) {
 
 TEST(BoundedRecursiveIteratorVecTest, CanMutatePointedToData) {
   std::vector<std::vector<std::vector<int>>> vec{{{1, 2}}, {{3}, {4, 5}}};
-  auto rit = make_recursive_iterator<2>(vec);
+  auto rit = recursive_iterator(vec, bounded<2>{});
   rit->clear();
   EXPECT_THAT(vec[0][0], IsEmpty());
 }