Bläddra i källkod

Merge branch 'refactor/naming/camelcase'

* refactor/naming/camelcase:
  refactor: rename test fixtures, fix some typos
  refactor: rename a few files chore: eliminate macro.h/undef.h
  refactor: change type names to CamelCase
Sam Jaffe 2 månader sedan
förälder
incheckning
5d1c6036f8
33 ändrade filer med 708 tillägg och 791 borttagningar
  1. 5 10
      include/iterator/capture_iterator.h
  2. 0 80
      include/iterator/cascade_iterator.h
  3. 3 3
      include/iterator/detail/arrow_proxy.h
  4. 0 25
      include/iterator/detail/macro.h
  5. 6 6
      include/iterator/detail/recursive_expander.h
  6. 0 21
      include/iterator/detail/undef.h
  7. 13 18
      include/iterator/end_aware_iterator.h
  8. 12 14
      include/iterator/indexed_iterator.h
  9. 3 7
      include/iterator/facade.h
  10. 12 17
      include/iterator/filter_iterator.h
  11. 13 9
      include/iterator/forwards.h
  12. 15 23
      include/iterator/join_iterator.h
  13. 81 0
      include/iterator/projecting_recursive_iterator.h
  14. 20 20
      include/iterator/proxy.h
  15. 29 36
      include/iterator/recursive_iterator.h
  16. 5 5
      include/iterator/unkeyed_iterator.h
  17. 12 15
      include/iterator/zip_iterator.h
  18. 24 32
      iterator.xcodeproj/project.pbxproj
  19. 2 2
      test/capture_iterator_test.cxx
  20. 21 21
      test/end_aware_iterator_test.cxx
  21. 147 0
      test/enumerate_iterator_test.cxx
  22. 18 18
      test/filter_iterator_test.cxx
  23. 0 145
      test/indexed_iterator_test.cxx
  24. 38 36
      test/join_iterator_test.cxx
  25. 14 12
      test/cascade_iterator_test.cxx
  26. 42 42
      test/recursive_iterator_accessors_test.cxx
  27. 19 19
      test/recursive_iterator_map_test.cxx
  28. 23 23
      test/recursive_iterator_mixed_container_test.cxx
  29. 11 11
      test/recursive_iterator_single_level_test.cxx
  30. 19 19
      test/recursive_iterator_vector_test.cxx
  31. 0 79
      test/unkeyed_iterator_test.cxx
  32. 78 0
      test/values_iterator_test.cxx
  33. 23 23
      test/zip_iterator_test.cxx

+ 5 - 10
include/iterator/capture_iterator.h

@@ -11,14 +11,11 @@
 #include <iterator/forwards.h>
 #include <iterator/proxy.h>
 
-#include <iterator/detail/macro.h>
-
 namespace iterator {
-
 template <typename It>
-class capture_iterator : public proxy<It, capture_iterator<It>> {
+class CaptureIterator : public Proxy<It, CaptureIterator<It>> {
 public:
-  using super_t = proxy<It, capture_iterator<It>>;
+  using super_t = Proxy<It, CaptureIterator<It>>;
   using value_type = typename std::iterator_traits<It>::value_type;
   using difference_type = typename std::iterator_traits<It>::difference_type;
 
@@ -26,8 +23,8 @@ private:
   value_type cache_;
 
 public:
-  capture_iterator() = default;
-  capture_iterator(It it) : super_t(it) { cache_ = super_t::dereference(); }
+  CaptureIterator() = default;
+  CaptureIterator(It it) : super_t(it) { cache_ = super_t::dereference(); }
 
   value_type const & dereference() const { return cache_; }
 
@@ -53,8 +50,6 @@ public:
   }
 };
 
-template <typename It> capture_iterator(It) -> capture_iterator<It>;
+template <typename It> CaptureIterator(It) -> CaptureIterator<It>;
 
 }
-
-#include <iterator/detail/undef.h>

+ 0 - 80
include/iterator/cascade_iterator.h

@@ -1,80 +0,0 @@
-#pragma once
-
-#include <cstddef>
-
-#include <iterator/concepts.h>
-#include <iterator/detail/projection_tuple.h>
-#include <iterator/detail/recursive_expander.h>
-#include <iterator/end_aware_iterator.h>
-#include <iterator/forwards.h>
-#include <iterator/recursive_iterator.h>
-
-namespace iterator {
-template <typename It, typename Projs, typename MaxDepth>
-class cascade_iterator;
-
-template <typename It, typename... Projs, typename MaxDepth>
-class cascade_iterator<It, detail::Projections<Projs...>, MaxDepth>
-    : public recursive_iterator_helper<It, MaxDepth,
-                                       detail::Projections<Projs...>>::type,
-      public facade<
-          cascade_iterator<It, detail::Projections<Projs...>, MaxDepth>> {
-public:
-  using sentinel_type = sentinel_t;
-
-public:
-  cascade_iterator() = default;
-
-  explicit cascade_iterator(Range auto & range, Projs... projs)
-      : cascade_iterator(end_aware_iterator(range), projs...) {}
-
-  explicit cascade_iterator(Range auto & range, MaxDepth, Projs... projs)
-      : cascade_iterator(end_aware_iterator(range), projs...) {}
-
-  explicit cascade_iterator(end_aware_iterator<It> iter, MaxDepth,
-                            Projs... projs)
-      : cascade_iterator::recursive_iterator_base(iter, projs...) {}
-
-  explicit cascade_iterator(end_aware_iterator<It> iter, Projs... projs)
-      : cascade_iterator::recursive_iterator_base(iter, projs...) {}
-
-  template <typename Ot>
-  explicit cascade_iterator(end_aware_iterator<Ot> other, Projs... projs)
-      : cascade_iterator(end_aware_iterator<It>(other), projs...) {}
-
-  template <typename Ot>
-  explicit cascade_iterator(end_aware_iterator<Ot> other, MaxDepth,
-                            Projs... projs)
-      : cascade_iterator(end_aware_iterator<It>(other), projs...) {}
-};
-
-template <Range R, typename... Projs>
-cascade_iterator(R, Projs...)
-    -> cascade_iterator<iterator_t<R>, detail::Projections<Projs...>,
-                        bounded<sizeof...(Projs) + 1>>;
-
-template <typename It, typename... Projs>
-cascade_iterator(end_aware_iterator<It>, Projs...)
-    -> cascade_iterator<It, detail::Projections<Projs...>,
-                        bounded<sizeof...(Projs) + 1>>;
-
-template <Range R, typename... Projs, size_t N>
-  requires(N > sizeof...(Projs))
-cascade_iterator(R, bounded<N>, Projs...)
-    -> cascade_iterator<iterator_t<R>, detail::Projections<Projs...>,
-                        bounded<N>>;
-
-template <typename It, typename... Projs, size_t N>
-  requires(N > sizeof...(Projs))
-cascade_iterator(end_aware_iterator<It>, bounded<N>, Projs...)
-    -> cascade_iterator<It, detail::Projections<Projs...>, bounded<N>>;
-
-template <Range R, typename... Projs>
-cascade_iterator(R, unbounded, Projs...)
-    -> cascade_iterator<iterator_t<R>, detail::Projections<Projs...>,
-                        unbounded>;
-
-template <typename It, typename... Projs>
-cascade_iterator(end_aware_iterator<It>, unbounded, Projs...)
-    -> cascade_iterator<It, detail::Projections<Projs...>, unbounded>;
-}

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

@@ -4,11 +4,11 @@
 #pragma once
 
 namespace iterator::detail {
-template <typename Reference> struct arrow_proxy {
-  arrow_proxy(Reference r) : r(std::move(r)) {}
+template <typename Reference> struct ArrowProxy {
+  ArrowProxy(Reference r) : r(std::move(r)) {}
   Reference r;
   Reference * operator->() { return std::addressof(r); }
 };
 
-template <typename R> arrow_proxy(R r) -> arrow_proxy<R>;
+template <typename R> ArrowProxy(R r) -> ArrowProxy<R>;
 }

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

@@ -1,25 +0,0 @@
-//
-//  macro.h
-//  iterator
-//
-//  Created by Sam Jaffe on 4/1/23.
-//  Copyright © 2023 Sam Jaffe. All rights reserved.
-//
-
-#ifndef _ITERATOR_MACRO_H
-#define _ITERATOR_MACRO_H
-
-#define FWD(x) std::forward<decltype(x)>(x)
-
-#define REQUIRES_T(trait, rval, ...) std::enable_if_t<trait, rval>
-#define REQUIRES(trait) typename = REQUIRES_T(trait, void)
-
-#define SFINAE(trait) template <bool _ = true, REQUIRES(trait && _)>
-
-#define VAL(X) std::declval<X>()
-#define DEREF_TYPE(X) decltype(*VAL(X))
-#define TYPE(X, EXPR) decltype(VAL(X).EXPR)
-#define EXISTS(EXPR) std::void_t<decltype(EXPR)>
-#define DEFER(TYPE) (std::is_void_v<TYPE> || true)
-
-#endif

+ 6 - 6
include/iterator/detail/recursive_expander.h

@@ -22,12 +22,12 @@ using projection_t = std::invoke_result_t<Proj, std::iter_reference_t<It>,
 template <typename It, typename Projs, typename MaxDepth, size_t N = 0,
           typename V = std::decay_t<projection_t<Projs, It, N>>>
 struct RecursiveExpander {
-  using type = std::tuple<end_aware_iterator<It>>;
+  using type = std::tuple<EndAwareIterator<It>>;
 };
 
 template <typename It, typename Projs, size_t N>
 struct RecursiveExpander<It, Projs, bounded<N + 1>, N> {
-  using type = std::tuple<end_aware_iterator<It>>;
+  using type = std::tuple<EndAwareIterator<It>>;
 };
 
 template <typename It, typename Projs, typename MaxDepth, size_t N, Range V>
@@ -37,8 +37,8 @@ struct RecursiveExpander<It, Projs, MaxDepth, N, V> {
   using expand_next = RecursiveExpander<iterator_t<projected_value_type>, Projs,
                                         MaxDepth, N + 1>;
 
-  using type = tuple_cat_t<std::tuple<end_aware_iterator<It>>,
-                           typename expand_next::type>;
+  using type =
+      tuple_cat_t<std::tuple<EndAwareIterator<It>>, typename expand_next::type>;
 };
 
 template <typename It, typename Projs, typename MaxDepth, size_t N,
@@ -51,7 +51,7 @@ struct RecursiveExpander<It, Projs, MaxDepth, N, V> {
   using expand_next = RecursiveExpander<iterator_t<projected_value_type>, Projs,
                                         MaxDepth, N + 1>;
 
-  using type = tuple_cat_t<std::tuple<end_aware_iterator<It>>,
-                           typename expand_next::type>;
+  using type =
+      tuple_cat_t<std::tuple<EndAwareIterator<It>>, typename expand_next::type>;
 };
 }

+ 0 - 21
include/iterator/detail/undef.h

@@ -1,21 +0,0 @@
-//
-//  undef.h
-//  iterator
-//
-//  Created by Sam Jaffe on 4/1/23.
-//  Copyright © 2023 Sam Jaffe. All rights reserved.
-//
-
-#ifdef _ITERATOR_MACRO_H
-#undef _ITERATOR_MACRO_H
-
-#undef FWD
-#undef SFINAE
-#undef REQUIRES
-#undef REQUIRES_T
-#undef EXISTS
-#undef TYPE
-#undef DEREF_TYPE
-#undef VAL
-
-#endif

+ 13 - 18
include/iterator/end_aware_iterator.h

@@ -12,30 +12,28 @@
 #include <iterator/proxy.h>
 #include <iterator/sentinel.h>
 
-#include <iterator/detail/macro.h>
-
 namespace iterator {
 /**
- * @class end_aware_iterator
+ * @class EndAwareIterator
  * @brief An iterator that keeps track of the relative end of the range.
  *
  * @tparam It The underlying iterator type
  */
 template <typename It>
-class end_aware_iterator : public proxy<It, end_aware_iterator<It>> {
+class EndAwareIterator : public Proxy<It, EndAwareIterator<It>> {
 public:
-  using super_t = proxy<It, end_aware_iterator<It>>;
+  using super_t = Proxy<It, EndAwareIterator<It>>;
   using sentinel_type = sentinel_t;
 
 public:
-  end_aware_iterator() = default;
-  end_aware_iterator(It it, It end) : super_t(it), end_(end) {}
+  EndAwareIterator() = default;
+  EndAwareIterator(It it, It end) : super_t(it), end_(end) {}
 
-  end_aware_iterator(Range auto & container)
+  EndAwareIterator(Range auto & container)
       : super_t(std::begin(container)), end_(std::end(container)) {}
 
   template <typename Ot>
-  end_aware_iterator(end_aware_iterator<Ot> const & other)
+  EndAwareIterator(EndAwareIterator<Ot> const & other)
       : super_t(other.impl()), end_(other.end_) {}
 
   operator std::ranges::subrange<It>() const {
@@ -50,7 +48,7 @@ public:
     }
   }
 
-  friend auto operator-(sentinel_type, end_aware_iterator const & self)
+  friend auto operator-(sentinel_type, EndAwareIterator const & self)
     requires(std::random_access_iterator<It>)
   {
     return self.end() - self.impl();
@@ -60,16 +58,13 @@ protected:
   It end() const { return end_; }
 
 private:
-  template <typename O> friend class end_aware_iterator;
+  template <typename O> friend class EndAwareIterator;
   It end_;
 };
 
-template <typename C>
-end_aware_iterator(C &&) -> end_aware_iterator<iterator_t<C>>;
-template <typename It> end_aware_iterator(It, It) -> end_aware_iterator<It>;
+template <typename C> EndAwareIterator(C &&) -> EndAwareIterator<iterator_t<C>>;
+template <typename It> EndAwareIterator(It, It) -> EndAwareIterator<It>;
 template <typename It>
-end_aware_iterator(end_aware_iterator<It>, end_aware_iterator<It>)
-    -> end_aware_iterator<It>;
+EndAwareIterator(EndAwareIterator<It>, EndAwareIterator<It>)
+    -> EndAwareIterator<It>;
 }
-
-#include <iterator/detail/undef.h>

+ 12 - 14
include/iterator/indexed_iterator.h

@@ -12,25 +12,23 @@
 #include <iterator/facade.h>
 #include <iterator/forwards.h>
 
-#include <iterator/detail/macro.h>
-
 namespace iterator {
 template <typename It>
-class indexed_iterator : public facade<indexed_iterator<It>> {
+class EnumerateIterator : public Facade<EnumerateIterator<It>> {
 public:
-  using reference = std::pair<size_t, DEREF_TYPE(It)>;
+  using reference = std::pair<size_t, std::iter_reference_t<It>>;
   using difference_type = typename std::iterator_traits<It>::difference_type;
 
 private:
-  using super_t = facade<indexed_iterator<It>>;
+  using super_t = Facade<EnumerateIterator<It>>;
 
 public:
-  indexed_iterator() = default;
-  indexed_iterator(It base) : base_(base) {}
-  indexed_iterator(It base, size_t idx) : base_(base), index_(idx) {}
+  EnumerateIterator() = default;
+  EnumerateIterator(It base) : base_(base) {}
+  EnumerateIterator(It base, size_t idx) : base_(base), index_(idx) {}
 
   template <typename O>
-  indexed_iterator(indexed_iterator<O> const & oiter)
+  EnumerateIterator(EnumerateIterator<O> const & oiter)
       : base_(oiter.base_), index_(oiter.index_) {}
 
   reference dereference() const { return {index_, *base_}; }
@@ -56,11 +54,11 @@ public:
     index_ += off;
   }
 
-  bool equal_to(indexed_iterator const & other) const {
+  bool equal_to(EnumerateIterator const & other) const {
     return base_ == other.base_;
   }
 
-  difference_type distance_to(indexed_iterator const & other) const
+  difference_type distance_to(EnumerateIterator const & other) const
     requires(std::random_access_iterator<It>)
   {
     return other.base_ - base_;
@@ -73,11 +71,11 @@ public:
   }
 
 private:
-  template <typename O> friend class indexed_iterator;
+  template <typename O> friend class EnumerateIterator;
   It base_;
   size_t index_{0};
 };
 
-template <typename It> indexed_iterator(It) -> indexed_iterator<It>;
-template <typename It> indexed_iterator(It, size_t) -> indexed_iterator<It>;
+template <typename It> EnumerateIterator(It) -> EnumerateIterator<It>;
+template <typename It> EnumerateIterator(It, size_t) -> EnumerateIterator<It>;
 }

+ 3 - 7
include/iterator/facade.h

@@ -6,10 +6,8 @@
 #include <iterator/concepts.h>
 #include <iterator/detail/arrow_proxy.h>
 
-#include <iterator/detail/macro.h>
-
 namespace iterator {
-template <typename CRTP> class facade {
+template <typename CRTP> class Facade {
 private:
   using self_type = CRTP;
 
@@ -20,7 +18,7 @@ public:
     if constexpr (std::is_reference<decltype(**this)>{}) {
       return std::addressof(**this);
     } else {
-      return detail::arrow_proxy{**this};
+      return detail::ArrowProxy{**this};
     }
   }
 
@@ -129,7 +127,7 @@ protected:
 }
 
 template <typename It>
-  requires std::is_base_of_v<iterator::facade<It>, It>
+  requires std::is_base_of_v<iterator::Facade<It>, It>
 struct std::iterator_traits<It> {
   static const It & _it;
   using reference = decltype(*_it);
@@ -143,5 +141,3 @@ struct std::iterator_traits<It> {
           std::conditional_t<::iterator::single_pass<It>, input_iterator_tag,
                              forward_iterator_tag>>>;
 };
-
-#include <iterator/detail/undef.h>

+ 12 - 17
include/iterator/filter_iterator.h

@@ -13,29 +13,26 @@
 #include <iterator/facade.h>
 #include <iterator/forwards.h>
 
-#include <iterator/detail/macro.h>
-
 namespace iterator {
 template <typename Iter, typename Pred>
-class filter_iterator : public facade<filter_iterator<Iter, Pred>> {
+class FilterIterator : public Facade<FilterIterator<Iter, Pred>> {
 public:
   using sentinel_type = sentinel_t;
-  using super_t = filter_iterator::facade;
+  using super_t = FilterIterator::Facade;
 
 public:
-  filter_iterator() = default;
+  FilterIterator() = default;
 
-  filter_iterator(Range auto & c, Pred pred)
-      : base_(c), pred_(std::move(pred)) {
+  FilterIterator(Range auto & c, Pred pred) : base_(c), pred_(std::move(pred)) {
     if (should_advance()) { increment(); }
   }
 
-  filter_iterator(Iter curr, Iter end, Pred pred)
-      : base_(end_aware_iterator(curr, end)), pred_(std::move(pred)) {
+  FilterIterator(Iter curr, Iter end, Pred pred)
+      : base_(EndAwareIterator(curr, end)), pred_(std::move(pred)) {
     if (should_advance()) { increment(); }
   }
 
-  filter_iterator(end_aware_iterator<Iter> curr, Pred pred)
+  FilterIterator(EndAwareIterator<Iter> curr, Pred pred)
       : base_(curr), pred_(std::move(pred)) {
     if (should_advance()) { increment(); }
   }
@@ -57,7 +54,7 @@ public:
   }
 
   bool at_end() const { return base_.at_end(); }
-  bool equal_to(filter_iterator const & other) const {
+  bool equal_to(FilterIterator const & other) const {
     return base_ == other.base_;
   }
 
@@ -66,16 +63,14 @@ public:
     return !base_.at_end() && !std::invoke(pred_, dereference());
   }
 
-  end_aware_iterator<Iter> base_;
+  EndAwareIterator<Iter> base_;
   Pred pred_;
 };
 
 template <typename C, typename P>
-filter_iterator(C &, P) -> filter_iterator<iterator_t<C>, P>;
+FilterIterator(C &, P) -> FilterIterator<iterator_t<C>, P>;
 template <typename It, typename P>
-filter_iterator(end_aware_iterator<It>, P) -> filter_iterator<It, P>;
+FilterIterator(EndAwareIterator<It>, P) -> FilterIterator<It, P>;
 template <typename It, typename P>
-filter_iterator(It, It, P) -> filter_iterator<It, P>;
+FilterIterator(It, It, P) -> FilterIterator<It, P>;
 }
-
-#include <iterator/detail/undef.h>

+ 13 - 9
include/iterator/forwards.h

@@ -14,24 +14,28 @@ namespace iterator {
 struct sentinel_t;
 
 // Iterator types
-template <typename It> class end_aware_iterator;
-template <typename It, typename Predicate> class filter_iterator;
-template <typename OIt> class joining_iterator;
-template <typename It> class unkeyed_iterator;
-template <typename... Its> class zip_iterator;
+template <typename It> class CaptureIterator;
+template <typename It> class EndAwareIterator;
+template <typename It> class EnumerateIterator;
+template <typename It, typename Pred> class FilterIterator;
+template <typename OIt> class JoinIterator;
+template <typename It> class ValuesIterator;
+template <typename... Its> class ZipIterator;
 
 struct unbounded {};
 template <size_t N>
   requires(N > 0)
 struct bounded {};
 
-template <typename It, typename MaxDepth = unbounded> class recursive_iterator;
+template <typename It, typename MaxDepth = unbounded> class RecursiveIterator;
 template <typename It, size_t N>
-using recursive_iterator_n = recursive_iterator<It, bounded<N>>;
+using RecursiveIteratorN = RecursiveIterator<It, bounded<N>>;
+template <typename It, typename Projs, typename MaxDepth>
+class ProjectingRecursiveIterator;
 
-template <typename CRTP> class facade;
+template <typename CRTP> class Facade;
 
 template <typename It, typename CRTP,
           typename = typename std::iterator_traits<It>::iterator_category>
-class proxy;
+class Proxy;
 }

+ 15 - 23
include/iterator/join_iterator.h

@@ -14,46 +14,41 @@
 #include <iterator/facade.h>
 #include <iterator/forwards.h>
 
-#include <iterator/detail/macro.h>
-
 namespace iterator {
-template <typename It>
-class joining_iterator : public facade<joining_iterator<It>> {
+template <typename It> class JoinIterator : public Facade<JoinIterator<It>> {
 private:
-  template <typename Ot> friend class joining_iterator;
-  constexpr static bool requires_caching = !std::is_reference_v<DEREF_TYPE(It)>;
+  template <typename Ot> friend class JoinIterator;
+  constexpr static bool requires_caching =
+      !std::is_reference_v<std::iter_reference_t<It>>;
 
 public:
   using sentinel_type = sentinel_t;
   using outer_iterator_t =
       std::conditional_t<requires_caching,
-                         capture_iterator<end_aware_iterator<It>>,
-                         end_aware_iterator<It>>;
+                         CaptureIterator<EndAwareIterator<It>>,
+                         EndAwareIterator<It>>;
   using inner_iterator_t =
-      end_aware_iterator<iterator_t<DEREF_TYPE(outer_iterator_t)>>;
+      EndAwareIterator<iterator_t<std::iter_reference_t<outer_iterator_t>>>;
 
 private:
   outer_iterator_t outer_;
   inner_iterator_t inner_;
 
 public:
-  joining_iterator() = default;
+  JoinIterator() = default;
 
   template <typename Ot>
-  joining_iterator(joining_iterator<Ot> const & other) : outer_(other.outer_) {
+  JoinIterator(JoinIterator<Ot> const & other) : outer_(other.outer_) {
     safely_init_inner_iterator(other.outer_, other.inner_);
   }
 
-  joining_iterator(Range auto & container) : outer_(FWD(container)) {
+  JoinIterator(Range auto & rng) : outer_(std::forward<decltype(rng)>(rng)) {
     update_iterator();
   }
 
-  joining_iterator(outer_iterator_t outer) : outer_(outer) {
-    update_iterator();
-  }
+  JoinIterator(outer_iterator_t outer) : outer_(outer) { update_iterator(); }
 
-  joining_iterator(outer_iterator_t const & outer,
-                   inner_iterator_t const & inner)
+  JoinIterator(outer_iterator_t const & outer, inner_iterator_t const & inner)
       : outer_(outer) {
     safely_init_inner_iterator(outer, inner);
   }
@@ -68,7 +63,7 @@ public:
   decltype(auto) dereference() const { return *inner_; }
 
   bool at_end() const { return outer_.at_end(); }
-  bool equal_to(joining_iterator const & other) const {
+  bool equal_to(JoinIterator const & other) const {
     return outer_ == other.outer_ && inner_ == other.inner_;
   }
 
@@ -94,9 +89,6 @@ private:
   }
 };
 
-template <typename C> joining_iterator(C &) -> joining_iterator<iterator_t<C>>;
-template <typename JI>
-joining_iterator(end_aware_iterator<JI>) -> joining_iterator<JI>;
+template <typename C> JoinIterator(C &) -> JoinIterator<iterator_t<C>>;
+template <typename JI> JoinIterator(EndAwareIterator<JI>) -> JoinIterator<JI>;
 }
-
-#include <iterator/detail/undef.h>

+ 81 - 0
include/iterator/projecting_recursive_iterator.h

@@ -0,0 +1,81 @@
+#pragma once
+
+#include <cstddef>
+
+#include <iterator/concepts.h>
+#include <iterator/detail/projection_tuple.h>
+#include <iterator/detail/recursive_expander.h>
+#include <iterator/end_aware_iterator.h>
+#include <iterator/forwards.h>
+#include <iterator/recursive_iterator.h>
+
+namespace iterator {
+template <typename It, typename... Projs, typename MaxDepth>
+class ProjectingRecursiveIterator<It, detail::Projections<Projs...>, MaxDepth>
+    : public RecursiveHelper<It, MaxDepth, detail::Projections<Projs...>>::type,
+      public Facade<ProjectingRecursiveIterator<
+          It, detail::Projections<Projs...>, MaxDepth>> {
+public:
+  using sentinel_type = sentinel_t;
+
+public:
+  ProjectingRecursiveIterator() = default;
+
+  explicit ProjectingRecursiveIterator(Range auto & range, Projs... projs)
+      : ProjectingRecursiveIterator(EndAwareIterator(range), projs...) {}
+
+  explicit ProjectingRecursiveIterator(Range auto & range, MaxDepth,
+                                       Projs... projs)
+      : ProjectingRecursiveIterator(EndAwareIterator(range), projs...) {}
+
+  explicit ProjectingRecursiveIterator(EndAwareIterator<It> iter, MaxDepth,
+                                       Projs... projs)
+      : ProjectingRecursiveIterator::RecursiveBase(iter, projs...) {}
+
+  explicit ProjectingRecursiveIterator(EndAwareIterator<It> iter,
+                                       Projs... projs)
+      : ProjectingRecursiveIterator::RecursiveBase(iter, projs...) {}
+
+  template <typename Ot>
+  explicit ProjectingRecursiveIterator(EndAwareIterator<Ot> other,
+                                       Projs... projs)
+      : ProjectingRecursiveIterator(EndAwareIterator<It>(other), projs...) {}
+
+  template <typename Ot>
+  explicit ProjectingRecursiveIterator(EndAwareIterator<Ot> other, MaxDepth,
+                                       Projs... projs)
+      : ProjectingRecursiveIterator(EndAwareIterator<It>(other), projs...) {}
+};
+
+template <Range R, typename... Projs>
+ProjectingRecursiveIterator(R, Projs...)
+    -> ProjectingRecursiveIterator<iterator_t<R>, detail::Projections<Projs...>,
+                                   bounded<sizeof...(Projs) + 1>>;
+
+template <typename It, typename... Projs>
+ProjectingRecursiveIterator(EndAwareIterator<It>, Projs...)
+    -> ProjectingRecursiveIterator<It, detail::Projections<Projs...>,
+                                   bounded<sizeof...(Projs) + 1>>;
+
+template <Range R, typename... Projs, size_t N>
+  requires(N > sizeof...(Projs))
+ProjectingRecursiveIterator(R, bounded<N>, Projs...)
+    -> ProjectingRecursiveIterator<iterator_t<R>, detail::Projections<Projs...>,
+                                   bounded<N>>;
+
+template <typename It, typename... Projs, size_t N>
+  requires(N > sizeof...(Projs))
+ProjectingRecursiveIterator(EndAwareIterator<It>, bounded<N>, Projs...)
+    -> ProjectingRecursiveIterator<It, detail::Projections<Projs...>,
+                                   bounded<N>>;
+
+template <Range R, typename... Projs>
+ProjectingRecursiveIterator(R, unbounded, Projs...)
+    -> ProjectingRecursiveIterator<iterator_t<R>, detail::Projections<Projs...>,
+                                   unbounded>;
+
+template <typename It, typename... Projs>
+ProjectingRecursiveIterator(EndAwareIterator<It>, unbounded, Projs...)
+    -> ProjectingRecursiveIterator<It, detail::Projections<Projs...>,
+                                   unbounded>;
+}

+ 20 - 20
include/iterator/proxy.h

@@ -3,11 +3,9 @@
 #include <iterator/facade.h>
 #include <iterator/forwards.h>
 
-#include <iterator/detail/macro.h>
-
 namespace iterator {
 template <typename It, typename Self, typename Cat>
-class proxy : public facade<Self> {
+class Proxy : public Facade<Self> {
 public:
   static constexpr bool single_pass_iterator = true;
 
@@ -15,9 +13,10 @@ private:
   It impl_;
 
 public:
-  proxy() = default;
-  proxy(It impl) : impl_(impl) {}
-  template <typename... Args> proxy(Args &&... args) : impl_(FWD(args)...) {}
+  Proxy() = default;
+  Proxy(It impl) : impl_(impl) {}
+  template <typename... Args>
+  Proxy(Args &&... args) : impl_(std::forward<Args>(args)...) {}
 
   decltype(auto) dereference() const { return *impl_; }
   void increment() { ++impl_; }
@@ -33,14 +32,15 @@ protected:
 };
 
 template <typename It, typename Self>
-class proxy<It, Self, std::forward_iterator_tag> : public facade<Self> {
+class Proxy<It, Self, std::forward_iterator_tag> : public Facade<Self> {
 private:
   It impl_;
 
 public:
-  proxy() = default;
-  proxy(It impl) : impl_(impl) {}
-  template <typename... Args> proxy(Args &&... args) : impl_(FWD(args)...) {}
+  Proxy() = default;
+  Proxy(It impl) : impl_(impl) {}
+  template <typename... Args>
+  Proxy(Args &&... args) : impl_(std::forward<Args>(args)...) {}
 
   decltype(auto) dereference() const { return *impl_; }
   void increment() { ++impl_; }
@@ -56,14 +56,15 @@ protected:
 };
 
 template <typename It, typename Self>
-class proxy<It, Self, std::bidirectional_iterator_tag> : public facade<Self> {
+class Proxy<It, Self, std::bidirectional_iterator_tag> : public Facade<Self> {
 private:
   It impl_;
 
 public:
-  proxy() = default;
-  proxy(It impl) : impl_(impl) {}
-  template <typename... Args> proxy(Args &&... args) : impl_(FWD(args)...) {}
+  Proxy() = default;
+  Proxy(It impl) : impl_(impl) {}
+  template <typename... Args>
+  Proxy(Args &&... args) : impl_(std::forward<Args>(args)...) {}
 
   decltype(auto) dereference() const { return *impl_; }
   void increment() { ++impl_; }
@@ -80,7 +81,7 @@ protected:
 };
 
 template <typename It, typename Self>
-class proxy<It, Self, std::random_access_iterator_tag> : public facade<Self> {
+class Proxy<It, Self, std::random_access_iterator_tag> : public Facade<Self> {
 public:
   using difference_type = typename std::iterator_traits<It>::difference_type;
 
@@ -88,9 +89,10 @@ private:
   It impl_;
 
 public:
-  proxy() = default;
-  proxy(It impl) : impl_(impl) {}
-  template <typename... Args> proxy(Args &&... args) : impl_(FWD(args)...) {}
+  Proxy() = default;
+  Proxy(It impl) : impl_(impl) {}
+  template <typename... Args>
+  Proxy(Args &&... args) : impl_(std::forward<Args>(args)...) {}
 
   decltype(auto) dereference() const { return *impl_; }
   void advance(difference_type off) { impl_ += off; }
@@ -113,5 +115,3 @@ protected:
   auto impl() const { return impl_; }
 };
 }
-
-#include <iterator/detail/undef.h>

+ 29 - 36
include/iterator/recursive_iterator.h

@@ -18,14 +18,11 @@
 #include <iterator/facade.h>
 #include <iterator/forwards.h>
 
-#include <iterator/detail/macro.h>
-
 namespace iterator {
-template <typename Tuple, typename Projs, typename Indices>
-class recursive_iterator_base;
+template <typename Tuple, typename Projs, typename Indices> class RecursiveBase;
 template <typename... It, typename... Projs, size_t... Is>
-class recursive_iterator_base<std::tuple<It...>, detail::Projections<Projs...>,
-                              std::index_sequence<Is...>>
+class RecursiveBase<std::tuple<It...>, detail::Projections<Projs...>,
+                    std::index_sequence<Is...>>
     : public std::tuple<It...>, private detail::Projections<Projs...> {
 public:
   static constexpr size_t LastIndex = sizeof...(It) - 1;
@@ -34,8 +31,8 @@ public:
   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>>(*this);
+  template <typename T> operator EndAwareIterator<T>() const {
+    return std::get<EndAwareIterator<T>>(*this);
   }
 
   decltype(auto) dereference() const {
@@ -54,13 +51,11 @@ public:
   void increment() { increment<>(); }
 
   bool at_end() const { return std::get<0>(*this).at_end(); }
-  bool equal_to(recursive_iterator_base const & other) const {
-    return *this == other;
-  }
+  bool equal_to(RecursiveBase const & other) const { return *this == other; }
 
 protected:
-  recursive_iterator_base() = default;
-  recursive_iterator_base(iterator_type<0> iter, Projs... projs)
+  RecursiveBase() = default;
+  RecursiveBase(iterator_type<0> iter, Projs... projs)
       : detail::Projections<Projs...>(projs...) {
     assign<0>(iter);
   }
@@ -95,7 +90,7 @@ private:
     }
   }
 
-  template <size_t I, typename T> void assign(end_aware_iterator<T> it) {
+  template <size_t I, typename T> void assign(EndAwareIterator<T> it) {
     std::get<I>(*this) = it;
     if constexpr (I < LastIndex) {
       if (!it.at_end()) {
@@ -106,7 +101,7 @@ private:
 
   template <size_t I, typename T> void assign(T && value) {
     if constexpr (Range<T>) {
-      assign<I>(end_aware_iterator(std::forward<T>(value)));
+      assign<I>(EndAwareIterator(std::forward<T>(value)));
     } else {
       assign<I>(std::get<1>(value));
     }
@@ -115,7 +110,7 @@ private:
 
 template <typename It, typename MaxDepth,
           typename Projs = detail::Projections<>>
-struct recursive_iterator_helper {
+struct RecursiveHelper {
   static typename detail::ProjectionExpander<It, Projs>::type const & _projs;
   using Projections = decltype(detail::Projections(_projs));
 
@@ -125,7 +120,7 @@ struct recursive_iterator_helper {
   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, Projections, indices>;
+  using type = RecursiveBase<iterator_tuple, Projections, indices>;
 };
 
 /**
@@ -143,39 +138,39 @@ struct recursive_iterator_helper {
  * 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>> {
+class RecursiveIterator : public RecursiveHelper<It, MaxDepth>::type,
+                          public Facade<RecursiveIterator<It, MaxDepth>> {
 public:
   using sentinel_type = sentinel_t;
 
 public:
-  recursive_iterator() = default;
+  RecursiveIterator() = default;
 
-  explicit recursive_iterator(Range auto & range, MaxDepth = {})
-      : recursive_iterator(end_aware_iterator(range)) {}
+  explicit RecursiveIterator(Range auto & range, MaxDepth = {})
+      : RecursiveIterator(EndAwareIterator(range)) {}
 
-  explicit recursive_iterator(end_aware_iterator<It> iter, MaxDepth = {})
-      : recursive_iterator::recursive_iterator_base(iter) {}
+  explicit RecursiveIterator(EndAwareIterator<It> iter, MaxDepth = {})
+      : RecursiveIterator::RecursiveBase(iter) {}
 
   template <typename Ot>
-  explicit recursive_iterator(end_aware_iterator<Ot> other, MaxDepth = {})
-      : recursive_iterator(end_aware_iterator<It>(other)) {}
+  explicit RecursiveIterator(EndAwareIterator<Ot> other, MaxDepth = {})
+      : RecursiveIterator(EndAwareIterator<It>(other)) {}
 
   template <typename Ot>
-  explicit recursive_iterator(recursive_iterator<Ot, MaxDepth> other)
-      : recursive_iterator(end_aware_iterator<Ot>(other)) {}
+  explicit RecursiveIterator(RecursiveIterator<Ot, MaxDepth> other)
+      : RecursiveIterator(EndAwareIterator<Ot>(other)) {}
 };
 
 template <typename Range, typename MaxDepth>
-recursive_iterator(Range &, MaxDepth)
-    -> recursive_iterator<iterator_t<Range>, MaxDepth>;
+RecursiveIterator(Range &, MaxDepth)
+    -> RecursiveIterator<iterator_t<Range>, MaxDepth>;
 template <typename Range>
-recursive_iterator(Range &) -> recursive_iterator<iterator_t<Range>, unbounded>;
+RecursiveIterator(Range &) -> RecursiveIterator<iterator_t<Range>, unbounded>;
 } // namespace iterator
 
 namespace std {
 template <size_t I, typename It, typename MaxDepth>
-auto get(::iterator::recursive_iterator<It, MaxDepth> const & iter) {
+auto get(::iterator::RecursiveIterator<It, MaxDepth> const & iter) {
   using return_type = std::decay_t<decltype(iter)>::template iterator_type<I>;
   return static_cast<return_type>(iter);
 }
@@ -185,14 +180,14 @@ 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 = recursive_iterator(std::forward<Rng>(rng), bounded<N>{});
+    auto begin = RecursiveIterator(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 = recursive_iterator(std::forward<Rng>(rng));
+    auto begin = RecursiveIterator(std::forward<Rng>(rng));
     return std::ranges::subrange(begin, decltype(begin)());
   }
 };
@@ -200,5 +195,3 @@ struct recursive_fn : std::ranges::range_adaptor_closure<recursive_fn> {
 template <size_t N> constexpr recursive_n_fn<N> recursive_n{};
 constexpr recursive_fn recursive;
 } // namespace iterator::views
-
-#include <iterator/detail/undef.h>

+ 5 - 5
include/iterator/unkeyed_iterator.h

@@ -20,16 +20,16 @@ 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 = recursive_iterator(object);
- * for (unkeyed_iterator<decltype(rit)> it = rit, end = {}; it != end; ++it) {
+ * auto const rit = RecursiveIterator(object);
+ * for (ValuesIterator<decltype(rit)> it = rit, end = {}; it != end; ++it) {
  *   // Process only BigType, discarding all of the keys that we need to walk
  * }
  * \endcode
  */
 template <typename Iterator>
-class unkeyed_iterator : public proxy<Iterator, unkeyed_iterator<Iterator>> {
+class ValuesIterator : public Proxy<Iterator, ValuesIterator<Iterator>> {
 public:
-  using proxy<Iterator, unkeyed_iterator<Iterator>>::proxy;
+  using Proxy<Iterator, ValuesIterator<Iterator>>::Proxy;
   decltype(auto) dereference() const {
     using value_type = typename Iterator::value_type;
     constexpr auto index = std::tuple_size<value_type>::value - 1;
@@ -37,5 +37,5 @@ public:
   }
 };
 
-template <typename It> unkeyed_iterator(It) -> unkeyed_iterator<It>;
+template <typename It> ValuesIterator(It) -> ValuesIterator<It>;
 }

+ 12 - 15
include/iterator/zip_iterator.h

@@ -7,17 +7,17 @@
 #include <iterator/forwards.h>
 
 namespace iterator::detail {
-template <typename Tuple, typename IS> class zip_iterator_impl;
+template <typename Tuple, typename IS> class ZipImpl;
 
 template <typename... Ts, size_t... Is>
-class zip_iterator_impl<std::tuple<Ts...>, std::index_sequence<Is...>> {
+class ZipImpl<std::tuple<Ts...>, std::index_sequence<Is...>> {
 public:
   using difference_type =
       std::common_type_t<typename std::iterator_traits<Ts>::difference_type...>;
 
 public:
-  zip_iterator_impl() = default;
-  zip_iterator_impl(Ts... iters) : _data(iters...) {}
+  ZipImpl() = default;
+  ZipImpl(Ts... iters) : _data(iters...) {}
 
   auto dereference() const {
     return std::forward_as_tuple(*std::get<Is>(_data)...);
@@ -37,11 +37,9 @@ public:
     [[maybe_unused]] auto l = {((std::get<Is>(_data) += d), 0)...};
   }
 
-  bool equal_to(zip_iterator_impl const & other) const {
-    return _data == other._data;
-  }
+  bool equal_to(ZipImpl const & other) const { return _data == other._data; }
 
-  auto distance_to(zip_iterator_impl const & other) const
+  auto distance_to(ZipImpl const & other) const
     requires(std::random_access_iterator<Ts> && ...)
   {
     return std::get<0>(other._data) - std::get<0>(_data);
@@ -56,16 +54,15 @@ namespace iterator {
 template <typename... Ts>
 using index_sequence = decltype(std::make_index_sequence<sizeof...(Ts)>{});
 template <typename... Ts>
-using zip_impl =
-    detail::zip_iterator_impl<std::tuple<Ts...>, index_sequence<Ts...>>;
+using ZipImpl = detail::ZipImpl<std::tuple<Ts...>, index_sequence<Ts...>>;
 
 template <typename... Iters>
-class zip_iterator : public zip_impl<Iters...>,
-                     public facade<zip_iterator<Iters...>> {
+class ZipIterator : public ZipImpl<Iters...>,
+                    public Facade<ZipIterator<Iters...>> {
 public:
-  zip_iterator() = default;
-  zip_iterator(Iters... iters) : zip_impl<Iters...>(iters...) {}
+  ZipIterator() = default;
+  ZipIterator(Iters... iters) : ZipImpl<Iters...>(iters...) {}
 };
 
-template <typename... It> zip_iterator(It...) -> zip_iterator<It...>;
+template <typename... It> ZipIterator(It...) -> ZipIterator<It...>;
 }

+ 24 - 32
iterator.xcodeproj/project.pbxproj

@@ -7,38 +7,36 @@
 	objects = {
 
 /* Begin PBXBuildFile section */
-		CD0AED842E836E1900E8B05D /* cascade_iterator.h in Headers */ = {isa = PBXBuildFile; fileRef = CD0AED832E836E1900E8B05D /* cascade_iterator.h */; };
+		CD0AED842E836E1900E8B05D /* projecting_recursive_iterator.h in Headers */ = {isa = PBXBuildFile; fileRef = CD0AED832E836E1900E8B05D /* projecting_recursive_iterator.h */; };
 		CD0AED892E836E4600E8B05D /* recursive_expander.h in Headers */ = {isa = PBXBuildFile; fileRef = CD0AED882E836E4600E8B05D /* recursive_expander.h */; };
 		CD0AED8B2E836E9F00E8B05D /* projection_tuple.h in Headers */ = {isa = PBXBuildFile; fileRef = CD0AED8A2E836E9F00E8B05D /* projection_tuple.h */; };
 		CD0AED8D2E836EF200E8B05D /* capture_fn.h in Headers */ = {isa = PBXBuildFile; fileRef = CD0AED8C2E836EF200E8B05D /* capture_fn.h */; };
-		CD0AED8F2E83FFC400E8B05D /* cascade_iterator_test.cxx in Sources */ = {isa = PBXBuildFile; fileRef = CD0AED8E2E83FFC400E8B05D /* cascade_iterator_test.cxx */; };
+		CD0AED8F2E83FFC400E8B05D /* projecting_recursive_iterator_test.cxx in Sources */ = {isa = PBXBuildFile; fileRef = CD0AED8E2E83FFC400E8B05D /* projecting_recursive_iterator_test.cxx */; };
 		CD41AFE32E7F13E4004F3E51 /* concepts.h in Headers */ = {isa = PBXBuildFile; fileRef = CD41AFE22E7F0434004F3E51 /* concepts.h */; };
 		CD41AFE42E7F13E4004F3E51 /* forwards.h in Headers */ = {isa = PBXBuildFile; fileRef = CDA2B6122858128C004D5353 /* forwards.h */; };
 		CD41AFE52E7F13E4004F3E51 /* facade.h in Headers */ = {isa = PBXBuildFile; fileRef = CDA2B6132858128C004D5353 /* facade.h */; };
 		CD41AFE62E7F13E4004F3E51 /* proxy.h in Headers */ = {isa = PBXBuildFile; fileRef = CDA2B61C2858128C004D5353 /* proxy.h */; };
 		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 */; };
-		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 */; };
 		CD41AFEF2E7F13E4004F3E51 /* filter_iterator.h in Headers */ = {isa = PBXBuildFile; fileRef = CDA2B61E2858128C004D5353 /* filter_iterator.h */; };
-		CD41AFF02E7F13E4004F3E51 /* indexed_iterator.h in Headers */ = {isa = PBXBuildFile; fileRef = CDA2B6142858128C004D5353 /* indexed_iterator.h */; };
+		CD41AFF02E7F13E4004F3E51 /* enumerate_iterator.h in Headers */ = {isa = PBXBuildFile; fileRef = CDA2B6142858128C004D5353 /* enumerate_iterator.h */; };
 		CD41AFF12E7F13E4004F3E51 /* join_iterator.h in Headers */ = {isa = PBXBuildFile; fileRef = CDA2B61F2858128C004D5353 /* join_iterator.h */; };
 		CD41AFF22E7F13E4004F3E51 /* recursive_iterator.h in Headers */ = {isa = PBXBuildFile; fileRef = CDA2B6162858128C004D5353 /* recursive_iterator.h */; };
-		CD41AFF32E7F13E4004F3E51 /* unkeyed_iterator.h in Headers */ = {isa = PBXBuildFile; fileRef = CDA2B6152858128C004D5353 /* unkeyed_iterator.h */; };
+		CD41AFF32E7F13E4004F3E51 /* values_iterator.h in Headers */ = {isa = PBXBuildFile; fileRef = CDA2B6152858128C004D5353 /* values_iterator.h */; };
 		CD41AFF42E7F13E4004F3E51 /* zip_iterator.h in Headers */ = {isa = PBXBuildFile; fileRef = CDA2B61D2858128C004D5353 /* zip_iterator.h */; };
 		CD5AEB3529D897DD00A390A4 /* capture_iterator_test.cxx in Sources */ = {isa = PBXBuildFile; fileRef = CD5AEB3429D897DD00A390A4 /* capture_iterator_test.cxx */; };
 		CDA2B62028581295004D5353 /* iterator in Headers */ = {isa = PBXBuildFile; fileRef = CDCB3BBC24E1CDE40029B771 /* iterator */; settings = {ATTRIBUTES = (Public, ); }; };
 		CDCB3BCA24E1D39B0029B771 /* GoogleMock.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = CDEC1E09235167920091D9F2 /* GoogleMock.framework */; };
 		CDCB3BD624E1D5320029B771 /* join_iterator_test.cxx in Sources */ = {isa = PBXBuildFile; fileRef = CDCB3BCD24E1D5320029B771 /* join_iterator_test.cxx */; };
-		CDCB3BD724E1D5320029B771 /* unkeyed_iterator_test.cxx in Sources */ = {isa = PBXBuildFile; fileRef = CDCB3BCE24E1D5320029B771 /* unkeyed_iterator_test.cxx */; };
+		CDCB3BD724E1D5320029B771 /* values_iterator_test.cxx in Sources */ = {isa = PBXBuildFile; fileRef = CDCB3BCE24E1D5320029B771 /* values_iterator_test.cxx */; };
 		CDCB3BD824E1D5320029B771 /* recursive_iterator_vector_test.cxx in Sources */ = {isa = PBXBuildFile; fileRef = CDCB3BCF24E1D5320029B771 /* recursive_iterator_vector_test.cxx */; };
 		CDCB3BD924E1D5320029B771 /* recursive_iterator_accessors_test.cxx in Sources */ = {isa = PBXBuildFile; fileRef = CDCB3BD024E1D5320029B771 /* recursive_iterator_accessors_test.cxx */; };
 		CDCB3BDA24E1D5320029B771 /* recursive_iterator_mixed_container_test.cxx in Sources */ = {isa = PBXBuildFile; fileRef = CDCB3BD124E1D5320029B771 /* recursive_iterator_mixed_container_test.cxx */; };
 		CDCB3BDB24E1D5320029B771 /* end_aware_iterator_test.cxx in Sources */ = {isa = PBXBuildFile; fileRef = CDCB3BD224E1D5320029B771 /* end_aware_iterator_test.cxx */; };
 		CDCB3BDC24E1D5320029B771 /* filter_iterator_test.cxx in Sources */ = {isa = PBXBuildFile; fileRef = CDCB3BD324E1D5320029B771 /* filter_iterator_test.cxx */; };
-		CDCB3BDD24E1D5320029B771 /* indexed_iterator_test.cxx in Sources */ = {isa = PBXBuildFile; fileRef = CDCB3BD424E1D5320029B771 /* indexed_iterator_test.cxx */; };
+		CDCB3BDD24E1D5320029B771 /* enumerate_iterator_test.cxx in Sources */ = {isa = PBXBuildFile; fileRef = CDCB3BD424E1D5320029B771 /* enumerate_iterator_test.cxx */; };
 		CDCB3BDE24E1D5320029B771 /* recursive_iterator_map_test.cxx in Sources */ = {isa = PBXBuildFile; fileRef = CDCB3BD524E1D5320029B771 /* recursive_iterator_map_test.cxx */; };
 		CDCB3BFC24E327CF0029B771 /* recursive_iterator_single_level_test.cxx in Sources */ = {isa = PBXBuildFile; fileRef = CDCB3BFB24E327CF0029B771 /* recursive_iterator_single_level_test.cxx */; };
 		CDCB3C0324E33A1E0029B771 /* zip_iterator_test.cxx in Sources */ = {isa = PBXBuildFile; fileRef = CDCB3C0224E33A1E0029B771 /* zip_iterator_test.cxx */; };
@@ -83,24 +81,22 @@
 /* End PBXContainerItemProxy section */
 
 /* Begin PBXFileReference section */
-		CD0AED832E836E1900E8B05D /* cascade_iterator.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = cascade_iterator.h; sourceTree = "<group>"; };
+		CD0AED832E836E1900E8B05D /* projecting_recursive_iterator.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = projecting_recursive_iterator.h; sourceTree = "<group>"; };
 		CD0AED882E836E4600E8B05D /* recursive_expander.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = recursive_expander.h; sourceTree = "<group>"; };
 		CD0AED8A2E836E9F00E8B05D /* projection_tuple.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = projection_tuple.h; sourceTree = "<group>"; };
 		CD0AED8C2E836EF200E8B05D /* capture_fn.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = capture_fn.h; sourceTree = "<group>"; };
-		CD0AED8E2E83FFC400E8B05D /* cascade_iterator_test.cxx */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = cascade_iterator_test.cxx; sourceTree = "<group>"; };
+		CD0AED8E2E83FFC400E8B05D /* projecting_recursive_iterator_test.cxx */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = projecting_recursive_iterator_test.cxx; sourceTree = "<group>"; };
 		CD3C6DDB26238F8F00548B64 /* xcode_gtest_helper.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = xcode_gtest_helper.h; sourceTree = "<group>"; };
 		CD41AFE22E7F0434004F3E51 /* concepts.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = concepts.h; sourceTree = "<group>"; };
 		CD5A8E7329D7910D008C2A4F /* sentinel.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = sentinel.h; sourceTree = "<group>"; };
 		CD5AEAE729D86D8100A390A4 /* ranges.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = ranges.h; sourceTree = "<group>"; };
-		CD5AEB3129D8885400A390A4 /* macro.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = macro.h; sourceTree = "<group>"; };
-		CD5AEB3229D8886200A390A4 /* undef.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = undef.h; sourceTree = "<group>"; };
 		CD5AEB3329D8956600A390A4 /* capture_iterator.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = capture_iterator.h; sourceTree = "<group>"; };
 		CD5AEB3429D897DD00A390A4 /* capture_iterator_test.cxx */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = capture_iterator_test.cxx; sourceTree = "<group>"; };
 		CDA2B60928581255004D5353 /* libiterator.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = libiterator.a; sourceTree = BUILT_PRODUCTS_DIR; };
 		CDA2B6122858128C004D5353 /* forwards.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = forwards.h; sourceTree = "<group>"; };
 		CDA2B6132858128C004D5353 /* facade.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = facade.h; sourceTree = "<group>"; };
-		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>"; };
+		CDA2B6142858128C004D5353 /* enumerate_iterator.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = enumerate_iterator.h; sourceTree = "<group>"; };
+		CDA2B6152858128C004D5353 /* values_iterator.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = values_iterator.h; sourceTree = "<group>"; };
 		CDA2B6162858128C004D5353 /* recursive_iterator.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = recursive_iterator.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>"; };
@@ -112,13 +108,13 @@
 		CDCB3BC124E1D3880029B771 /* iterator-test.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = "iterator-test.xctest"; sourceTree = BUILT_PRODUCTS_DIR; };
 		CDCB3BC524E1D3880029B771 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
 		CDCB3BCD24E1D5320029B771 /* join_iterator_test.cxx */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = join_iterator_test.cxx; sourceTree = "<group>"; };
-		CDCB3BCE24E1D5320029B771 /* unkeyed_iterator_test.cxx */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = unkeyed_iterator_test.cxx; sourceTree = "<group>"; };
+		CDCB3BCE24E1D5320029B771 /* values_iterator_test.cxx */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = values_iterator_test.cxx; sourceTree = "<group>"; };
 		CDCB3BCF24E1D5320029B771 /* recursive_iterator_vector_test.cxx */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = recursive_iterator_vector_test.cxx; sourceTree = "<group>"; };
 		CDCB3BD024E1D5320029B771 /* recursive_iterator_accessors_test.cxx */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = recursive_iterator_accessors_test.cxx; sourceTree = "<group>"; };
 		CDCB3BD124E1D5320029B771 /* recursive_iterator_mixed_container_test.cxx */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = recursive_iterator_mixed_container_test.cxx; sourceTree = "<group>"; };
 		CDCB3BD224E1D5320029B771 /* end_aware_iterator_test.cxx */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = end_aware_iterator_test.cxx; sourceTree = "<group>"; };
 		CDCB3BD324E1D5320029B771 /* filter_iterator_test.cxx */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = filter_iterator_test.cxx; sourceTree = "<group>"; };
-		CDCB3BD424E1D5320029B771 /* indexed_iterator_test.cxx */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = indexed_iterator_test.cxx; sourceTree = "<group>"; };
+		CDCB3BD424E1D5320029B771 /* enumerate_iterator_test.cxx */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = enumerate_iterator_test.cxx; sourceTree = "<group>"; };
 		CDCB3BD524E1D5320029B771 /* recursive_iterator_map_test.cxx */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = recursive_iterator_map_test.cxx; sourceTree = "<group>"; };
 		CDCB3BFB24E327CF0029B771 /* recursive_iterator_single_level_test.cxx */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = recursive_iterator_single_level_test.cxx; sourceTree = "<group>"; };
 		CDCB3C0224E33A1E0029B771 /* zip_iterator_test.cxx */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = zip_iterator_test.cxx; sourceTree = "<group>"; };
@@ -172,17 +168,17 @@
 				CD3C6DDB26238F8F00548B64 /* xcode_gtest_helper.h */,
 				CD5AEAE729D86D8100A390A4 /* ranges.h */,
 				CD5AEB3429D897DD00A390A4 /* capture_iterator_test.cxx */,
-				CD0AED8E2E83FFC400E8B05D /* cascade_iterator_test.cxx */,
 				CDCB3BD224E1D5320029B771 /* end_aware_iterator_test.cxx */,
+				CDCB3BD424E1D5320029B771 /* enumerate_iterator_test.cxx */,
 				CDCB3BD324E1D5320029B771 /* filter_iterator_test.cxx */,
-				CDCB3BD424E1D5320029B771 /* indexed_iterator_test.cxx */,
 				CDCB3BCD24E1D5320029B771 /* join_iterator_test.cxx */,
+				CD0AED8E2E83FFC400E8B05D /* projecting_recursive_iterator_test.cxx */,
 				CDCB3BD024E1D5320029B771 /* recursive_iterator_accessors_test.cxx */,
 				CDCB3BD124E1D5320029B771 /* recursive_iterator_mixed_container_test.cxx */,
 				CDCB3BD524E1D5320029B771 /* recursive_iterator_map_test.cxx */,
 				CDCB3BCF24E1D5320029B771 /* recursive_iterator_vector_test.cxx */,
 				CDCB3BFB24E327CF0029B771 /* recursive_iterator_single_level_test.cxx */,
-				CDCB3BCE24E1D5320029B771 /* unkeyed_iterator_test.cxx */,
+				CDCB3BCE24E1D5320029B771 /* values_iterator_test.cxx */,
 				CDCB3C0224E33A1E0029B771 /* zip_iterator_test.cxx */,
 			);
 			path = test;
@@ -206,13 +202,13 @@
 				CD5A8E7329D7910D008C2A4F /* sentinel.h */,
 				CDA2B6172858128C004D5353 /* detail */,
 				CD5AEB3329D8956600A390A4 /* capture_iterator.h */,
-				CD0AED832E836E1900E8B05D /* cascade_iterator.h */,
+				CD0AED832E836E1900E8B05D /* projecting_recursive_iterator.h */,
 				CDA2B61B2858128C004D5353 /* end_aware_iterator.h */,
 				CDA2B61E2858128C004D5353 /* filter_iterator.h */,
-				CDA2B6142858128C004D5353 /* indexed_iterator.h */,
+				CDA2B6142858128C004D5353 /* enumerate_iterator.h */,
 				CDA2B61F2858128C004D5353 /* join_iterator.h */,
 				CDA2B6162858128C004D5353 /* recursive_iterator.h */,
-				CDA2B6152858128C004D5353 /* unkeyed_iterator.h */,
+				CDA2B6152858128C004D5353 /* values_iterator.h */,
 				CDA2B61D2858128C004D5353 /* zip_iterator.h */,
 			);
 			path = iterator;
@@ -222,8 +218,6 @@
 			isa = PBXGroup;
 			children = (
 				CDA2B61A2858128C004D5353 /* arrow_proxy.h */,
-				CD5AEB3129D8885400A390A4 /* macro.h */,
-				CD5AEB3229D8886200A390A4 /* undef.h */,
 				CD0AED8A2E836E9F00E8B05D /* projection_tuple.h */,
 				CD0AED8C2E836EF200E8B05D /* capture_fn.h */,
 				CD0AED882E836E4600E8B05D /* recursive_expander.h */,
@@ -272,18 +266,16 @@
 				CD0AED892E836E4600E8B05D /* recursive_expander.h in Headers */,
 				CD41AFE72E7F13E4004F3E51 /* sentinel.h in Headers */,
 				CD41AFE82E7F13E4004F3E51 /* arrow_proxy.h in Headers */,
-				CD41AFE92E7F13E4004F3E51 /* macro.h in Headers */,
-				CD41AFEC2E7F13E4004F3E51 /* undef.h in Headers */,
 				CD0AED8D2E836EF200E8B05D /* capture_fn.h in Headers */,
 				CD41AFED2E7F13E4004F3E51 /* capture_iterator.h in Headers */,
 				CD41AFEE2E7F13E4004F3E51 /* end_aware_iterator.h in Headers */,
-				CD0AED842E836E1900E8B05D /* cascade_iterator.h in Headers */,
+				CD0AED842E836E1900E8B05D /* projecting_recursive_iterator.h in Headers */,
 				CD41AFEF2E7F13E4004F3E51 /* filter_iterator.h in Headers */,
 				CD0AED8B2E836E9F00E8B05D /* projection_tuple.h in Headers */,
-				CD41AFF02E7F13E4004F3E51 /* indexed_iterator.h in Headers */,
+				CD41AFF02E7F13E4004F3E51 /* enumerate_iterator.h in Headers */,
 				CD41AFF12E7F13E4004F3E51 /* join_iterator.h in Headers */,
 				CD41AFF22E7F13E4004F3E51 /* recursive_iterator.h in Headers */,
-				CD41AFF32E7F13E4004F3E51 /* unkeyed_iterator.h in Headers */,
+				CD41AFF32E7F13E4004F3E51 /* values_iterator.h in Headers */,
 				CD41AFF42E7F13E4004F3E51 /* zip_iterator.h in Headers */,
 			);
 			runOnlyForDeploymentPostprocessing = 0;
@@ -428,11 +420,11 @@
 				CDCB3BDB24E1D5320029B771 /* end_aware_iterator_test.cxx in Sources */,
 				CDCB3BD824E1D5320029B771 /* recursive_iterator_vector_test.cxx in Sources */,
 				CDCB3BDC24E1D5320029B771 /* filter_iterator_test.cxx in Sources */,
-				CD0AED8F2E83FFC400E8B05D /* cascade_iterator_test.cxx in Sources */,
+				CD0AED8F2E83FFC400E8B05D /* projecting_recursive_iterator_test.cxx in Sources */,
 				CDCB3BDE24E1D5320029B771 /* recursive_iterator_map_test.cxx in Sources */,
-				CDCB3BDD24E1D5320029B771 /* indexed_iterator_test.cxx in Sources */,
+				CDCB3BDD24E1D5320029B771 /* enumerate_iterator_test.cxx in Sources */,
 				CDCB3BD624E1D5320029B771 /* join_iterator_test.cxx in Sources */,
-				CDCB3BD724E1D5320029B771 /* unkeyed_iterator_test.cxx in Sources */,
+				CDCB3BD724E1D5320029B771 /* values_iterator_test.cxx in Sources */,
 				CDCB3BDA24E1D5320029B771 /* recursive_iterator_mixed_container_test.cxx in Sources */,
 				CDCB3C0324E33A1E0029B771 /* zip_iterator_test.cxx in Sources */,
 				CDCB3BD924E1D5320029B771 /* recursive_iterator_accessors_test.cxx in Sources */,

+ 2 - 2
test/capture_iterator_test.cxx

@@ -11,7 +11,7 @@
 #include "ranges.h"
 #include "xcode_gtest_helper.h"
 
-using iterator::capture_iterator;
+using iterator::CaptureIterator;
 
 using testing::Address;
 using testing::ElementsAre;
@@ -36,7 +36,7 @@ TEST(CaptureIterator, UnderlyingReturnsUnique) {
 }
 
 TEST(CaptureIterator, CachesValue) {
-  auto it = capture_iterator(fake_iterator());
+  auto it = CaptureIterator(fake_iterator());
 
   auto const & result = *it;
   EXPECT_THAT(*it, Address(&result));

+ 21 - 21
test/end_aware_iterator_test.cxx

@@ -5,12 +5,12 @@
 
 #include "xcode_gtest_helper.h"
 
-using iterator::end_aware_iterator;
+using iterator::EndAwareIterator;
 
 TEST(EndAwareIterator, IStreamIterator) {
   std::stringstream ss{"0 1 2 3"};
-  end_aware_iterator eai{std::istream_iterator<int>(ss),
-                         std::istream_iterator<int>()};
+  EndAwareIterator eai{std::istream_iterator<int>(ss),
+                       std::istream_iterator<int>()};
 
   EXPECT_TRUE(iterator::single_pass<decltype(eai)>);
 }
@@ -18,61 +18,61 @@ TEST(EndAwareIterator, IStreamIterator) {
 // TODO: This ought to be implemented as a compiles-test
 TEST(EndAwareIterator, CanCastCompatibleIterators) {
   std::vector<int> v{1, 2, 3, 4, 5};
-  end_aware_iterator eai(v.begin(), v.end());
+  EndAwareIterator eai(v.begin(), v.end());
 
-  end_aware_iterator<std::vector<int>::const_iterator>{eai};
+  EndAwareIterator<std::vector<int>::const_iterator>{eai};
 }
 
 TEST(EndAwareIterator, BeginWrapperIsEqualToBegin) {
   std::vector<int> v{1, 2, 3, 4, 5};
 
-  EXPECT_EQ(*v.begin(), *end_aware_iterator(v.begin(), v.end()));
+  EXPECT_THAT(*v.begin(), *EndAwareIterator(v.begin(), v.end()));
 }
 
 TEST(EndAwareIterator, MutableActionsArePassthrough) {
   std::vector<int> v{1, 2, 3, 4, 5};
-  *end_aware_iterator(v.begin(), v.end()) = -1;
+  *EndAwareIterator(v.begin(), v.end()) = -1;
 
-  EXPECT_EQ(v[0], -1);
+  EXPECT_THAT(v[0], -1);
 }
 
 TEST(EndAwareIterator, CanTellYouThatItsReachedEnd) {
   std::vector<int> v{1, 2, 3, 4, 5};
-  end_aware_iterator it{v.end() - 1, v.end()};
+  EndAwareIterator it{v.end() - 1, v.end()};
   EXPECT_FALSE(it.at_end());
   ++it;
-  EXPECT_EQ(it, end_aware_iterator(v.end(), v.end()));
+  EXPECT_THAT(it, EndAwareIterator(v.end(), v.end()));
   EXPECT_TRUE(it.at_end());
 }
 
 TEST(EndAwareIterator, EmptyIteratorIsEnd) {
-  EXPECT_TRUE(end_aware_iterator<std::vector<int>::iterator>().at_end());
+  EXPECT_TRUE(EndAwareIterator<std::vector<int>::iterator>().at_end());
 }
 
 TEST(EndAwareIterator, PreIncrementAdvancesIterator) {
   std::vector<int> v{1, 2, 3, 4, 5};
-  end_aware_iterator eai(v.begin(), v.end());
+  EndAwareIterator eai(v.begin(), v.end());
 
-  EXPECT_EQ(*eai, 1);
-  EXPECT_EQ(*++eai, 2);
-  EXPECT_EQ(*eai, 2);
+  EXPECT_THAT(*eai, 1);
+  EXPECT_THAT(*++eai, 2);
+  EXPECT_THAT(*eai, 2);
 }
 
 TEST(EndAwareIterator, PostIncrementReturnsCopyOfPrev) {
   std::vector<int> v{1, 2, 3, 4, 5};
-  end_aware_iterator eai(v.begin(), v.end());
+  EndAwareIterator eai(v.begin(), v.end());
 
-  EXPECT_EQ(*eai, 1);
-  EXPECT_EQ(*eai++, 1);
-  EXPECT_EQ(*eai, 2);
+  EXPECT_THAT(*eai, 1);
+  EXPECT_THAT(*eai++, 1);
+  EXPECT_THAT(*eai, 2);
 }
 
 TEST(EndAwareIterator, CanIterateWithSentinel) {
   std::vector<int> v{1, 2, 3, 4, 5};
   size_t count{0};
-  for (end_aware_iterator it(v); it != iterator::sentinel; ++it) {
+  for (EndAwareIterator it(v); it != iterator::sentinel; ++it) {
     ++count;
   }
 
-  EXPECT_EQ(count, 5);
+  EXPECT_THAT(count, 5);
 }

+ 147 - 0
test/enumerate_iterator_test.cxx

@@ -0,0 +1,147 @@
+#include "iterator/enumerate_iterator.h"
+
+#include <map>
+#include <vector>
+
+#include "iterator/end_aware_iterator.h"
+
+#include "ranges.h"
+#include "xcode_gtest_helper.h"
+
+using iterator::EndAwareIterator;
+using iterator::EnumerateIterator;
+
+using testing::Ge;
+using testing::Gt;
+using testing::Le;
+using testing::Lt;
+using testing::Ne;
+
+// TODO: This ought to be implemented as a compiles-test
+TEST(EnumerateIteartor, CanCastCompatibleIterators) {
+  std::vector<int> v{1, 2, 3, 4, 5};
+  EnumerateIterator eai(v.begin());
+  EnumerateIterator<std::vector<int>::const_iterator>{eai};
+}
+
+TEST(EnumerateIteartor, CanLieAboutIndex) {
+  std::vector<int> vec{5, 3, 2, 8, 9, 11, 2, 4};
+  EnumerateIterator it(vec.begin(), 3);
+  EXPECT_THAT(it->first, 3);
+}
+
+TEST(EnumerateIteartor, FakeIndexDoesntEffectEqualityCheck) {
+  std::vector<int> vec{5, 3, 2, 8, 9, 11, 2, 4};
+  EXPECT_THAT(EnumerateIterator(vec.begin()),
+              EnumerateIterator(vec.begin(), 3));
+  EXPECT_THAT(EnumerateIterator(vec.begin()) + 3,
+              Ne(EnumerateIterator(vec.begin(), 3)));
+}
+
+TEST(EnumerateIteartor, DoesNotTrackByIndex) {
+  std::vector<int> vec{5, 3, 2, 8, 9, 11, 2, 4};
+  EnumerateIterator end(vec.end());
+  EXPECT_THAT(decltype(end){}, Ne(end));
+}
+
+TEST(EnumerateIteartor, IteratorPropagatesAtEnd) {
+  std::vector<int> vec{5, 3, 2, 8, 9, 11, 2, 4};
+  EnumerateIterator end(EndAwareIterator(vec.end(), vec.end()));
+
+  EXPECT_THAT(end, iterator::sentinel);
+}
+
+TEST(EnumerateIteartor, CanCompareIteratorOrder) {
+  std::vector<int> vec{5, 3, 2, 8, 9, 11, 2, 4};
+  EnumerateIterator const begin(vec.begin());
+  EnumerateIterator const it = begin + 3;
+
+  EXPECT_THAT(begin, Lt(it));
+  EXPECT_THAT(begin, Le(it));
+  EXPECT_THAT(it, Le(it));
+  EXPECT_THAT(it, Gt(begin));
+  EXPECT_THAT(it, Ge(begin));
+  EXPECT_THAT(it, Ge(it));
+}
+
+TEST(EnumerateIteartor, PreIncrementAdvancesIterator) {
+  std::vector<int> vec{5, 3, 2, 8, 9, 11, 2, 4};
+  EnumerateIterator it(vec.begin() + 1);
+  EXPECT_THAT(it->second, 3);
+  EXPECT_THAT((++it)->second, 2);
+  EXPECT_THAT(it->second, 2);
+}
+
+TEST(EnumerateIteartor, PostIncrementReturnsCopyOfPrev) {
+  std::vector<int> vec{5, 3, 2, 8, 9, 11, 2, 4};
+  EnumerateIterator it(vec.begin() + 1);
+  EXPECT_THAT(it->second, 3);
+  EXPECT_THAT((it++)->second, 3);
+  EXPECT_THAT(it->second, 2);
+}
+
+TEST(EnumerateIteartor, PreDecrementAdvancesIterator) {
+  std::vector<int> vec{5, 3, 2, 8, 9, 11, 2, 4};
+  EnumerateIterator it(vec.begin() + 1);
+  EXPECT_THAT(it->second, 3);
+  EXPECT_THAT((--it)->second, 5);
+  EXPECT_THAT(it->second, 5);
+}
+
+TEST(EnumerateIteartor, PostDecrementReturnsCopyOfPrev) {
+  std::vector<int> vec{5, 3, 2, 8, 9, 11, 2, 4};
+  EnumerateIterator it(vec.begin() + 1);
+  EXPECT_THAT(it->second, 3);
+  EXPECT_THAT((it--)->second, 3);
+  EXPECT_THAT(it->second, 5);
+}
+
+TEST(EnumerateIteartor, CanWalkNStepsForward) {
+  std::vector<int> vec{5, 3, 2, 8, 9, 11, 2, 4};
+  EnumerateIterator const begin(vec.begin());
+  EnumerateIterator it = begin;
+  it += 4;
+  EXPECT_THAT(ranges::distance(begin, it), 4);
+}
+
+TEST(EnumerateIteartor, CanWalkNStepsBackwards) {
+  std::vector<int> vec{5, 3, 2, 8, 9, 11, 2, 4};
+  EnumerateIterator const end(vec.end());
+  EnumerateIterator it = end;
+  it -= 4;
+  EXPECT_THAT(ranges::distance(it, end), 4);
+}
+
+TEST(EnumerateIteartor, RandomAccessIsPassthrough) {
+  std::vector<int> vec{5, 3, 2, 8, 9, 11, 2, 4};
+  EXPECT_THAT(EnumerateIterator(vec.begin()) + 4,
+              EnumerateIterator(vec.begin() + 4));
+  EXPECT_THAT(EnumerateIterator(vec.end()) - 4,
+              EnumerateIterator(vec.end() - 4));
+}
+
+TEST(EnumerateIteartor, TreatsVectorIteratorAsPairIdxValue) {
+  std::vector<int> vec{5, 3, 2, 8, 9, 11, 2, 4};
+  std::vector<std::pair<int, int>> const expected{
+      {0, 5}, {1, 3}, {2, 2}, {3, 8}, {4, 9}, {5, 11}, {6, 2}, {7, 4}};
+
+  std::vector<std::pair<int, int>> const result(EnumerateIterator(vec.begin()),
+                                                EnumerateIterator(vec.end()));
+  EXPECT_THAT(result, expected);
+}
+
+TEST(EnumerateIteartor, TreatsVectorIteratorAsMapIdxToValue) {
+  std::vector<int> vec{5, 3, 2, 8, 9, 11, 2, 4};
+  std::map<int, int> const expected{{0, 5}, {1, 3},  {2, 2}, {3, 8},
+                                    {4, 9}, {5, 11}, {6, 2}, {7, 4}};
+
+  std::map<int, int> const result(EnumerateIterator(vec.begin()),
+                                  EnumerateIterator(vec.end()));
+  EXPECT_THAT(result, expected);
+}
+
+TEST(EnumerateIteartor, CanMutatePointedToData) {
+  std::vector<int> vec{5, 3, 2, 8, 9, 11, 2, 4};
+  EnumerateIterator(vec.begin() + 4, 4)->second = -1;
+  EXPECT_THAT(vec[4], -1);
+}

+ 18 - 18
test/filter_iterator_test.cxx

@@ -5,62 +5,62 @@
 #include "ranges.h"
 #include "xcode_gtest_helper.h"
 
-using iterator::filter_iterator;
+using iterator::FilterIterator;
 
 bool is_even(int i) { return i % 2 == 0; }
 
 TEST(FilterIterator, CanPerformSkipsOnData) {
   std::vector<int> const data = {1, 2, 3, 4, 5};
-  filter_iterator it(data, is_even);
+  FilterIterator it(data, is_even);
 
-  EXPECT_EQ(ranges::distance(it, iterator::sentinel), 2);
-  EXPECT_EQ(*it++, 2);
-  EXPECT_EQ(*it++, 4);
+  EXPECT_THAT(ranges::distance(it, iterator::sentinel), 2);
+  EXPECT_THAT(*it++, 2);
+  EXPECT_THAT(*it++, 4);
 }
 
 // TODO: Maybe this should actually move
 TEST(FilterIterator, MutatingContainerDoesNotMoveIterator) {
   std::vector<int> data = {1, 2, 3, 4, 5};
-  filter_iterator it(data, is_even);
+  FilterIterator it(data, is_even);
 
-  EXPECT_EQ(ranges::distance(it, iterator::sentinel), 2);
+  EXPECT_THAT(ranges::distance(it, iterator::sentinel), 2);
 
   *it = 1;
-  EXPECT_EQ(ranges::distance(it, iterator::sentinel), 2);
-  EXPECT_EQ(*it, 1);
+  EXPECT_THAT(ranges::distance(it, iterator::sentinel), 2);
+  EXPECT_THAT(*it, 1);
 }
 
 TEST(FilterIterator, CanConstructFilterFromSubRange) {
   std::vector<int> data = {1, 2, 3, 4, 5};
-  filter_iterator it(data.begin(), data.begin() + 3, is_even);
+  FilterIterator it(data.begin(), data.begin() + 3, is_even);
 
-  EXPECT_EQ(ranges::distance(it, iterator::sentinel), 1);
+  EXPECT_THAT(ranges::distance(it, iterator::sentinel), 1);
 }
 
 TEST(FilterIterator, IfNonMatchThenStartIsEnd) {
   std::vector<int> const data = {1, 3, 5};
-  filter_iterator it(data, is_even);
+  FilterIterator it(data, is_even);
 
-  EXPECT_EQ(it, iterator::sentinel);
+  EXPECT_THAT(it, iterator::sentinel);
 }
 
 TEST(FilterIterator, CapsIterationAtEnd) {
   std::vector<int> const data = {1, 2, 3, 4, 5};
-  filter_iterator it(data, is_even);
+  FilterIterator it(data, is_even);
 
   ++ ++it;
-  EXPECT_EQ(it, iterator::sentinel);
+  EXPECT_THAT(it, iterator::sentinel);
 
   ++it;
-  EXPECT_EQ(it, iterator::sentinel);
+  EXPECT_THAT(it, iterator::sentinel);
 }
 
 TEST(FilterIterator, CanIterateWithSentinel) {
   std::vector<int> v{1, 2, 3, 4, 5};
   size_t count{0};
-  for (filter_iterator it(v, is_even); it != iterator::sentinel; ++it) {
+  for (FilterIterator it(v, is_even); it != iterator::sentinel; ++it) {
     ++count;
   }
 
-  EXPECT_EQ(count, 2);
+  EXPECT_THAT(count, 2);
 }

+ 0 - 145
test/indexed_iterator_test.cxx

@@ -1,145 +0,0 @@
-#include "iterator/indexed_iterator.h"
-
-#include <map>
-#include <vector>
-
-#include "iterator/end_aware_iterator.h"
-
-#include "ranges.h"
-#include "xcode_gtest_helper.h"
-
-using iterator::end_aware_iterator;
-using iterator::indexed_iterator;
-
-using testing::Ge;
-using testing::Gt;
-using testing::Le;
-using testing::Lt;
-using testing::Ne;
-
-// TODO: This ought to be implemented as a compiles-test
-TEST(IndexedIteratorTest, CanCastCompatibleIterators) {
-  std::vector<int> v{1, 2, 3, 4, 5};
-  indexed_iterator eai(v.begin());
-  indexed_iterator<std::vector<int>::const_iterator>{eai};
-}
-
-TEST(IndexedIteratorTest, CanLieAboutIndex) {
-  std::vector<int> vec{5, 3, 2, 8, 9, 11, 2, 4};
-  indexed_iterator it(vec.begin(), 3);
-  EXPECT_THAT(it->first, 3);
-}
-
-TEST(IndexedIteratorTest, FakeIndexDoesntEffectEqualityCheck) {
-  std::vector<int> vec{5, 3, 2, 8, 9, 11, 2, 4};
-  EXPECT_THAT(indexed_iterator(vec.begin()), indexed_iterator(vec.begin(), 3));
-  EXPECT_THAT(indexed_iterator(vec.begin()) + 3,
-              Ne(indexed_iterator(vec.begin(), 3)));
-}
-
-TEST(IndexedIteratorTest, DoesNotTrackByIndex) {
-  std::vector<int> vec{5, 3, 2, 8, 9, 11, 2, 4};
-  indexed_iterator end(vec.end());
-  EXPECT_THAT(decltype(end){}, Ne(end));
-}
-
-TEST(IndexedIteratorTest, IteratorPropagatesAtEnd) {
-  std::vector<int> vec{5, 3, 2, 8, 9, 11, 2, 4};
-  indexed_iterator end(end_aware_iterator(vec.end(), vec.end()));
-
-  EXPECT_EQ(end, iterator::sentinel);
-}
-
-TEST(IndexedIteratorTest, CanCompareIteratorOrder) {
-  std::vector<int> vec{5, 3, 2, 8, 9, 11, 2, 4};
-  indexed_iterator const begin(vec.begin());
-  indexed_iterator const it = begin + 3;
-
-  EXPECT_THAT(begin, Lt(it));
-  EXPECT_THAT(begin, Le(it));
-  EXPECT_THAT(it, Le(it));
-  EXPECT_THAT(it, Gt(begin));
-  EXPECT_THAT(it, Ge(begin));
-  EXPECT_THAT(it, Ge(it));
-}
-
-TEST(IndexedIteratorTest, PreIncrementAdvancesIterator) {
-  std::vector<int> vec{5, 3, 2, 8, 9, 11, 2, 4};
-  indexed_iterator it(vec.begin() + 1);
-  EXPECT_THAT(it->second, 3);
-  EXPECT_THAT((++it)->second, 2);
-  EXPECT_THAT(it->second, 2);
-}
-
-TEST(IndexedIteratorTest, PostIncrementReturnsCopyOfPrev) {
-  std::vector<int> vec{5, 3, 2, 8, 9, 11, 2, 4};
-  indexed_iterator it(vec.begin() + 1);
-  EXPECT_THAT(it->second, 3);
-  EXPECT_THAT((it++)->second, 3);
-  EXPECT_THAT(it->second, 2);
-}
-
-TEST(IndexedIteratorTest, PreDecrementAdvancesIterator) {
-  std::vector<int> vec{5, 3, 2, 8, 9, 11, 2, 4};
-  indexed_iterator it(vec.begin() + 1);
-  EXPECT_THAT(it->second, 3);
-  EXPECT_THAT((--it)->second, 5);
-  EXPECT_THAT(it->second, 5);
-}
-
-TEST(IndexedIteratorTest, PostDecrementReturnsCopyOfPrev) {
-  std::vector<int> vec{5, 3, 2, 8, 9, 11, 2, 4};
-  indexed_iterator it(vec.begin() + 1);
-  EXPECT_THAT(it->second, 3);
-  EXPECT_THAT((it--)->second, 3);
-  EXPECT_THAT(it->second, 5);
-}
-
-TEST(IndexedIteratorTest, CanWalkNStepsForward) {
-  std::vector<int> vec{5, 3, 2, 8, 9, 11, 2, 4};
-  indexed_iterator const begin(vec.begin());
-  indexed_iterator it = begin;
-  it += 4;
-  EXPECT_THAT(ranges::distance(begin, it), 4);
-}
-
-TEST(IndexedIteratorTest, CanWalkNStepsBackwards) {
-  std::vector<int> vec{5, 3, 2, 8, 9, 11, 2, 4};
-  indexed_iterator const end(vec.end());
-  indexed_iterator it = end;
-  it -= 4;
-  EXPECT_THAT(ranges::distance(it, end), 4);
-}
-
-TEST(IndexedIteratorTest, RandomAccessIsPassthrough) {
-  std::vector<int> vec{5, 3, 2, 8, 9, 11, 2, 4};
-  EXPECT_THAT(indexed_iterator(vec.begin()) + 4,
-              indexed_iterator(vec.begin() + 4));
-  EXPECT_THAT(indexed_iterator(vec.end()) - 4, indexed_iterator(vec.end() - 4));
-}
-
-TEST(IndexedIteratorTest, TreatsVectorIteratorAsPairIdxValue) {
-  std::vector<int> vec{5, 3, 2, 8, 9, 11, 2, 4};
-  std::vector<std::pair<int, int>> const expected{
-      {0, 5}, {1, 3}, {2, 2}, {3, 8}, {4, 9}, {5, 11}, {6, 2}, {7, 4}};
-
-  std::vector<std::pair<int, int>> const result(indexed_iterator(vec.begin()),
-                                                indexed_iterator(vec.end()));
-  EXPECT_THAT(result, expected);
-}
-
-TEST(IndexedIteratorTest, TreatsVectorIteratorAsMapIdxToValue) {
-  std::vector<int> vec{5, 3, 2, 8, 9, 11, 2, 4};
-  std::map<int, int> const expected{{0, 5}, {1, 3},  {2, 2}, {3, 8},
-                                    {4, 9}, {5, 11}, {6, 2}, {7, 4}};
-
-  std::map<int, int> const result(indexed_iterator(vec.begin()),
-                                  indexed_iterator(vec.end()));
-  EXPECT_THAT(result, expected);
-}
-
-TEST(IndexedIteratorTest, CanMutatePointedToData) {
-  std::vector<int> vec{5, 3, 2, 8, 9, 11, 2, 4};
-  indexed_iterator(vec.begin() + 4, 4)->second = -1;
-  EXPECT_THAT(vec[4], -1);
-}

+ 38 - 36
test/join_iterator_test.cxx

@@ -4,74 +4,76 @@
 
 #include "xcode_gtest_helper.h"
 
-using iterator::end_aware_iterator;
-using iterator::joining_iterator;
+using iterator::EndAwareIterator;
+using iterator::JoinIterator;
 
-TEST(JoinIteratorTest, FirstDereferencedElemIsTheFirstInTheChain) {
+using testing::Not;
+
+TEST(JoinIterator, FirstDereferencedElemIsTheFirstInTheChain) {
   std::vector<std::vector<int>> mv{{1, 2, 3}, {4, 5, 6}};
-  EXPECT_EQ(*joining_iterator(mv), mv[0][0]);
+  EXPECT_THAT(*JoinIterator(mv), mv[0][0]);
 }
 
-TEST(JoinIteratorTest, HoldsReferenceToContainedElements) {
+TEST(JoinIterator, HoldsReferenceToContainedElements) {
   std::vector<std::vector<int>> mv{{1, 2, 3}, {4, 5, 6}};
-  EXPECT_EQ(joining_iterator(mv).operator->(), &mv[0][0]);
+  EXPECT_THAT(JoinIterator(mv).operator->(), &mv[0][0]);
 }
 
-TEST(JoinIteratorTest, EmptyContainerBeginIsEnd) {
+TEST(JoinIterator, EmptyContainerBeginIsEnd) {
   std::vector<std::vector<int>> mv{{1, 2, 3}, {4, 5, 6}};
-  joining_iterator it(mv);
-  EXPECT_NE(it, iterator::sentinel);
+  JoinIterator it(mv);
+  EXPECT_THAT(it, Not(iterator::sentinel));
 
   mv.clear();
-  EXPECT_EQ(joining_iterator(mv), iterator::sentinel);
+  EXPECT_THAT(JoinIterator(mv), iterator::sentinel);
 }
 
 // TODO: This ought to be implemented as a compiles-test
-TEST(JoinIteratorTest, CanCastCompatibleIterators) {
+TEST(JoinIterator, CanCastCompatibleIterators) {
   std::vector<std::vector<int>> mv{{1, 2, 3}, {4, 5, 6}};
-  joining_iterator it(mv);
-  iterator::joining_iterator<decltype(mv)::const_iterator>{it};
+  JoinIterator it(mv);
+  iterator::JoinIterator<decltype(mv)::const_iterator>{it};
 }
 
-TEST(JoinIteratorTest, CanAccessInternalIterator) {
+TEST(JoinIterator, CanAccessInternalIterator) {
   std::vector<std::vector<int>> mv{{1, 2, 3}, {4, 5, 6}};
-  auto eai = end_aware_iterator(mv);
-  joining_iterator it(eai);
-  EXPECT_EQ(it.outer_iterator(), eai);
+  auto eai = EndAwareIterator(mv);
+  JoinIterator it(eai);
+  EXPECT_THAT(it.outer_iterator(), eai);
 }
 
-TEST(JoinIteratorTest, CanAccessChildIterator) {
+TEST(JoinIterator, CanAccessChildIterator) {
   std::vector<std::vector<int>> mv{{1, 2, 3}, {4, 5, 6}};
-  joining_iterator it(mv);
-  EXPECT_EQ(it.inner_iterator(), end_aware_iterator(mv[0]));
+  JoinIterator it(mv);
+  EXPECT_THAT(it.inner_iterator(), EndAwareIterator(mv[0]));
 }
 
-TEST(JoinIteratorTest, PreIncrementAdvancesIterator) {
+TEST(JoinIterator, PreIncrementAdvancesIterator) {
   std::vector<std::vector<int>> mv{{1, 2, 3}, {4, 5, 6}};
-  joining_iterator it(mv);
-  EXPECT_EQ(*it, 1);
-  EXPECT_EQ(*++it, 2);
-  EXPECT_EQ(*it, 2);
+  JoinIterator it(mv);
+  EXPECT_THAT(*it, 1);
+  EXPECT_THAT(*++it, 2);
+  EXPECT_THAT(*it, 2);
 }
 
-TEST(JoinIteratorTest, PostIncrementReturnsCopyOfPrev) {
+TEST(JoinIterator, PostIncrementReturnsCopyOfPrev) {
   std::vector<std::vector<int>> mv{{1, 2, 3}, {4, 5, 6}};
-  joining_iterator it(mv);
-  EXPECT_EQ(*it, 1);
-  EXPECT_EQ(*it++, 1);
-  EXPECT_EQ(*it, 2);
+  JoinIterator it(mv);
+  EXPECT_THAT(*it, 1);
+  EXPECT_THAT(*it++, 1);
+  EXPECT_THAT(*it, 2);
 }
 
-TEST(JoinIteratorTest, MovesFromListToListWhenReachingEnd) {
+TEST(JoinIterator, MovesFromListToListWhenReachingEnd) {
   std::vector<std::vector<int>> mv{{1, 2, 3}, {4, 5, 6}};
-  joining_iterator it(mv);
+  JoinIterator it(mv);
   std::advance(it, 2);
-  EXPECT_EQ(*++it, mv[1][0]);
+  EXPECT_THAT(*++it, mv[1][0]);
 }
 
-TEST(JoinIteratorTest, SkipsOverEmptyElements) {
+TEST(JoinIterator, SkipsOverEmptyElements) {
   std::vector<std::vector<int>> mv{{1, 2, 3}, {}, {4, 5, 6}};
-  joining_iterator it(mv);
+  JoinIterator it(mv);
   std::advance(it, 2);
-  EXPECT_EQ(*++it, mv[2][0]);
+  EXPECT_THAT(*++it, mv[2][0]);
 }

+ 14 - 12
test/cascade_iterator_test.cxx

@@ -6,12 +6,12 @@
 //  Copyright © 2025 Sam Jaffe. All rights reserved.
 //
 
-#include "iterator/cascade_iterator.h"
+#include "iterator/projecting_recursive_iterator.h"
 
 #include "ranges.h"
 #include "xcode_gtest_helper.h"
 
-using iterator::cascade_iterator;
+using iterator::ProjectingRecursiveIterator;
 
 struct Baz {
   std::vector<int> ints;
@@ -31,29 +31,30 @@ struct Foo {
   std::vector<Bar> bars_copy() { return bars_; }
 };
 
-TEST(CascadeIteratorTest, OneProjectorIsTwoLevels) {
+TEST(ProjectingRecursiveIterator, OneProjectorIsTwoLevels) {
   std::vector<Foo> foos;
-  auto iter = cascade_iterator(foos, &Foo::bars);
+  auto iter = ProjectingRecursiveIterator(foos, &Foo::bars);
   testing::StaticAssertTypeEq<decltype(*iter), Bar const &>();
 }
 
-TEST(CascadeIteratorTest, TwoProjectorIsThreeLevels) {
+TEST(ProjectingRecursiveIterator, TwoProjectorIsThreeLevels) {
   std::vector<Foo> foos;
-  auto iter = cascade_iterator(foos, &Foo::bars, &Bar::bazes);
+  auto iter = ProjectingRecursiveIterator(foos, &Foo::bars, &Bar::bazes);
   testing::StaticAssertTypeEq<decltype(*iter),
                               std::tuple<int const &, Baz const &>>();
 }
 
-TEST(CascadeIteratorTest, IsRvalueSafe) {
+TEST(ProjectingRecursiveIterator, IsRvalueSafe) {
   std::vector<Foo> foos;
-  auto iter = cascade_iterator(foos, &Foo::bars_copy, &Bar::bazes);
+  auto iter = ProjectingRecursiveIterator(foos, &Foo::bars_copy, &Bar::bazes);
   testing::StaticAssertTypeEq<decltype(*iter),
                               std::tuple<int const &, Baz const &>>();
 }
 
-TEST(CascadeIteratorTest, CanProjectUnboundedTail) {
+TEST(ProjectingRecursiveIterator, CanProjectUnboundedTail) {
   std::vector<Foo> foos;
-  auto iter = cascade_iterator(foos, iterator::unbounded{}, &Foo::example);
+  auto iter =
+      ProjectingRecursiveIterator(foos, iterator::unbounded{}, &Foo::example);
   static_assert(
       std::same_as<decltype(*iter),
                    std::tuple<int const &, std::string const &, int &>>);
@@ -61,9 +62,10 @@ TEST(CascadeIteratorTest, CanProjectUnboundedTail) {
       decltype(*iter), std::tuple<int const &, std::string const &, int &>>();
 }
 
-TEST(CascadeIteratorTest, CanProjectBoundedTail) {
+TEST(ProjectingRecursiveIterator, CanProjectBoundedTail) {
   std::vector<Foo> foos;
-  auto iter = cascade_iterator(foos, iterator::bounded<3>{}, &Foo::example);
+  auto iter =
+      ProjectingRecursiveIterator(foos, iterator::bounded<3>{}, &Foo::example);
   static_assert(
       std::same_as<decltype(*iter),
                    std::tuple<int const &, std::string const &, int &>>);

+ 42 - 42
test/recursive_iterator_accessors_test.cxx

@@ -9,95 +9,95 @@
 #include "xcode_gtest_helper.h"
 
 using iterator::bounded;
-using iterator::end_aware_iterator;
-using iterator::recursive_iterator;
+using iterator::EndAwareIterator;
+using iterator::RecursiveIterator;
 
 using testing::ElementsAreArray;
 using testing::Not;
 using testing::StaticAssertTypeEq;
 
-TEST(RecursiveIteratorTest, DoesNotUnwrapString) {
+TEST(RecursiveIterator, DoesNotUnwrapString) {
   std::vector<std::string> obj{"A", "B", "C", "D"};
-  auto rit = recursive_iterator(obj);
+  auto rit = RecursiveIterator(obj);
   StaticAssertTypeEq<decltype(rit.operator->()), std::string *>();
 
   EXPECT_THAT(obj | views::recursive | ranges::to<std::vector>(),
               ElementsAreArray(obj));
 }
 
-TEST(RecursiveIteratorTest, CanArrowMultiVector) {
+TEST(RecursiveIterator, CanArrowMultiVector) {
   std::vector<std::vector<int>> obj{{{0, 1}}, {{2, 3}}};
-  auto rit = recursive_iterator(obj);
+  auto rit = RecursiveIterator(obj);
   StaticAssertTypeEq<decltype(rit.operator->()), int *>();
   EXPECT_THAT(rit.operator->(), &obj[0][0]);
 }
 
-TEST(RecursiveIteratorTest, CanAccessOuterterator) {
+TEST(RecursiveIterator, CanAccessOuterterator) {
   std::map<int, std::vector<int>> obj{{1, {{0, 1}}}, {2, {{2, 3}}}};
-  auto rit = recursive_iterator(obj);
+  auto rit = RecursiveIterator(obj);
 
-  end_aware_iterator<decltype(obj)::iterator> inner = rit;
+  EndAwareIterator<decltype(obj)::iterator> inner = rit;
   EXPECT_THAT(&std::get<0>(*rit), &(inner->first));
 }
 
-TEST(RecursiveIteratorTest, CanAccessInnerIterator) {
+TEST(RecursiveIterator, CanAccessInnerIterator) {
   std::map<int, std::vector<int>> obj{{1, {{0, 1}}}, {2, {{2, 3}}}};
-  auto rit = recursive_iterator(obj);
+  auto rit = RecursiveIterator(obj);
 
-  end_aware_iterator<std::vector<int>::iterator> inner = rit;
+  EndAwareIterator<std::vector<int>::iterator> inner = rit;
   EXPECT_THAT(&std::get<1>(*rit), &*inner);
 }
 
-TEST(RecursiveIteratorTest, CanStdGetToAllLayersOfInternalIteration) {
+TEST(RecursiveIterator, CanStdGetToAllLayersOfInternalIteration) {
   std::map<int, std::vector<std::map<int, int>>> obj{
       {1, {{{1, 1}}, {{2, 2}}}}, // 2 1-element maps
       {2, {{{3, 3}, {4, 4}}}}    // 1 2-element map
   };
-  auto rit = recursive_iterator(obj);
+  auto rit = RecursiveIterator(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>>();
+                     EndAwareIterator<mvm_iterator>>();
 
   using vm_iterator = std::vector<std::map<int, int>>::iterator;
   StaticAssertTypeEq<decltype(std::get<1>(rit)),
-                     end_aware_iterator<vm_iterator>>();
+                     EndAwareIterator<vm_iterator>>();
 
   using m_iterator = std::map<int, int>::iterator;
   StaticAssertTypeEq<decltype(std::get<2>(rit)),
-                     end_aware_iterator<m_iterator>>();
+                     EndAwareIterator<m_iterator>>();
 
   using tup_i_i_i = std::tuple<int const &, int const &, int &>;
   StaticAssertTypeEq<decltype(*rit), tup_i_i_i>();
 }
 
-TEST(RecursiveIteratorTest, CanAccessInternalIteratorsWithGet) {
+TEST(RecursiveIterator, CanAccessInternalIteratorsWithGet) {
   std::map<int, std::vector<std::map<int, int>>> obj{
       {1, {{{1, 1}}, {{2, 2}}}}, // 2 1-element maps
       {2, {{{3, 3}, {4, 4}}}}    // 1 2-element map
   };
-  auto rit = recursive_iterator(obj);
-  EXPECT_THAT(std::get<0>(rit), end_aware_iterator(obj));
-  EXPECT_THAT(std::get<1>(rit), end_aware_iterator(obj[1]));
-  EXPECT_THAT(std::get<2>(rit), end_aware_iterator(obj[1][0]));
+  auto rit = RecursiveIterator(obj);
+  EXPECT_THAT(std::get<0>(rit), EndAwareIterator(obj));
+  EXPECT_THAT(std::get<1>(rit), EndAwareIterator(obj[1]));
+  EXPECT_THAT(std::get<2>(rit), EndAwareIterator(obj[1][0]));
 }
 
 // TODO: This ought to be implemented as a compiles-test
-TEST(RecursiveIteratorTest, CanCastCompatibleIterators) {
+TEST(RecursiveIterator, CanCastCompatibleIterators) {
   std::map<int, std::vector<std::map<int, int>>> obj{
       {1, {{{1, 1}}, {{2, 2}}}}, // 2 1-element maps
       {2, {{{3, 3}, {4, 4}}}}    // 1 2-element map
   };
-  auto rit = recursive_iterator(obj);
-  iterator::recursive_iterator<decltype(obj)::const_iterator> cit(rit);
+  auto rit = RecursiveIterator(obj);
+  iterator::RecursiveIterator<decltype(obj)::const_iterator> cit(rit);
 }
 
-TEST(RecursiveIteratorTest, EmptyCtorIsEnd) {
+TEST(RecursiveIterator, EmptyCtorIsEnd) {
   std::map<int, std::vector<std::map<int, int>>> obj{
       {1, {{{1, 1}}, {{2, 2}}}}, // 2 1-element maps
       {2, {{{3, 3}, {4, 4}}}}    // 1 2-element map
   };
-  auto rit = recursive_iterator(obj);
+  auto rit = RecursiveIterator(obj);
 
   EXPECT_THAT(rit, Not(iterator::sentinel));
   EXPECT_THAT(ranges::distance(rit, iterator::sentinel), 4);
@@ -106,51 +106,51 @@ TEST(RecursiveIteratorTest, EmptyCtorIsEnd) {
   EXPECT_THAT(rit, iterator::sentinel);
 }
 
-TEST(BoundedRecursiveIteratorTest, CanStdGetToNLayersOfInternalIteration) {
+TEST(RecursiveIterator_Bounded, CanStdGetToNLayersOfInternalIteration) {
   std::map<int, std::vector<std::map<int, int>>> obj{
       {1, {{{1, 1}}, {{2, 2}}}}, // 2 1-element maps
       {2, {{{3, 3}, {4, 4}}}}    // 1 2-element map
   };
-  auto rit = recursive_iterator(obj, bounded<2>{});
+  auto rit = RecursiveIterator(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>>();
+                     EndAwareIterator<mvm_iterator>>();
 
   using vm_iterator = std::vector<std::map<int, int>>::iterator;
   StaticAssertTypeEq<decltype(std::get<1>(rit)),
-                     end_aware_iterator<vm_iterator>>();
+                     EndAwareIterator<vm_iterator>>();
 
   using tup_i_mii = std::tuple<int const &, std::map<int, int> &>;
   StaticAssertTypeEq<decltype(*rit), tup_i_mii>();
 }
 
-TEST(BoundedRecursiveIteratorTest, CanAccessInternalIteratorsWithGet) {
+TEST(RecursiveIterator_Bounded, CanAccessInternalIteratorsWithGet) {
   std::map<int, std::vector<std::map<int, int>>> obj{
       {1, {{{1, 1}}, {{2, 2}}}}, // 2 1-element maps
       {2, {{{3, 3}, {4, 4}}}}    // 1 2-element map
   };
-  auto rit = recursive_iterator(obj, bounded<2>{});
-  EXPECT_THAT(std::get<0>(rit), end_aware_iterator(obj));
-  EXPECT_THAT(std::get<1>(rit), end_aware_iterator(obj[1]));
+  auto rit = RecursiveIterator(obj, bounded<2>{});
+  EXPECT_THAT(std::get<0>(rit), EndAwareIterator(obj));
+  EXPECT_THAT(std::get<1>(rit), EndAwareIterator(obj[1]));
 }
 
 // TODO: This ought to be implemented as a compiles-test
-TEST(BoundedRecursiveIteratorTest, CanCastCompatibleIterators) {
+TEST(RecursiveIterator_Bounded, CanCastCompatibleIterators) {
   std::map<int, std::vector<std::map<int, int>>> obj{
       {1, {{{1, 1}}, {{2, 2}}}}, // 2 1-element maps
       {2, {{{3, 3}, {4, 4}}}}    // 1 2-element map
   };
-  auto rit = recursive_iterator(obj, bounded<2>{});
-  iterator::recursive_iterator_n<decltype(obj)::const_iterator, 2> cit(rit);
+  auto rit = RecursiveIterator(obj, bounded<2>{});
+  iterator::RecursiveIteratorN<decltype(obj)::const_iterator, 2> cit(rit);
 }
 
-TEST(BoundedRecursiveIteratorTest, EmptyCtorIsEnd) {
+TEST(RecursiveIterator_Bounded, EmptyCtorIsEnd) {
   std::map<int, std::vector<std::map<int, int>>> obj{
       {1, {{{1, 1}}, {{2, 2}}}}, // 2 1-element maps
       {2, {{{3, 3}, {4, 4}}}}    // 1 2-element map
   };
-  auto rit = recursive_iterator(obj, bounded<3>{});
+  auto rit = RecursiveIterator(obj, bounded<3>{});
   EXPECT_THAT(rit, Not(iterator::sentinel));
   EXPECT_THAT(ranges::distance(rit, iterator::sentinel), 4);
 
@@ -158,11 +158,11 @@ TEST(BoundedRecursiveIteratorTest, EmptyCtorIsEnd) {
   EXPECT_THAT(rit, iterator::sentinel);
 }
 
-TEST(BoundedRecursiveIteratorTest, CanFetchInnerCollections) {
+TEST(RecursiveIterator_Bounded, CanFetchInnerCollections) {
   std::vector<std::vector<std::map<int, int>>> obj{
       {{{{1, 1}}, {{2, 2}}}}, // 2 1-element maps
       {{{{3, 3}, {4, 4}}}}    // 1 2-element map
   };
-  auto rit = recursive_iterator(obj, bounded<2>{});
+  auto rit = RecursiveIterator(obj, bounded<2>{});
   EXPECT_THAT(*rit, obj[0][0]);
 }

+ 19 - 19
test/recursive_iterator_map_test.cxx

@@ -11,38 +11,38 @@
 #include "xcode_gtest_helper.h"
 
 using iterator::bounded;
-using iterator::recursive_iterator;
+using iterator::RecursiveIterator;
 
 using testing::ElementsAreArray;
 using testing::IsEmpty;
 
-TEST(RecursiveIteratorMapTest, PreIncrementAdvancesIterator) {
+TEST(RecursiveIterator_MapMap, 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 = recursive_iterator(map);
+  auto rit = RecursiveIterator(map);
   EXPECT_THAT(std::get<3>(*rit), 1);
   EXPECT_THAT(std::get<3>(*++rit), 2);
   EXPECT_THAT(std::get<3>(*rit), 2);
 }
 
-TEST(RecursiveIteratorMapTest, PostIncrementReturnsCopyOfPrev) {
+TEST(RecursiveIterator_MapMap, 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 = recursive_iterator(map);
+  auto rit = RecursiveIterator(map);
   EXPECT_THAT(std::get<3>(*rit), 1);
   EXPECT_THAT(std::get<3>(*rit++), 1);
   EXPECT_THAT(std::get<3>(*rit), 2);
 }
 
-TEST(RecursiveIteratorMapTest, IterDistanceIsSumOfInnerContainerSizes) {
+TEST(RecursiveIterator_MapMap, 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 = recursive_iterator(map);
+  auto rit = RecursiveIterator(map);
 
   EXPECT_THAT(ranges::distance(rit, iterator::sentinel), 4);
 }
 
-TEST(RecursiveIteratorMapTest, ElementsAreUnwrappedAsATuple) {
+TEST(RecursiveIterator_MapMap, ElementsAreUnwrappedAsATuple) {
   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}}}}}};
   std::vector<std::tuple<int, int, int, int>> const expected{
@@ -52,41 +52,41 @@ TEST(RecursiveIteratorMapTest, ElementsAreUnwrappedAsATuple) {
               ElementsAreArray(expected));
 }
 
-TEST(RecursiveIteratorMapTest, CanMutatePointedToData) {
+TEST(RecursiveIterator_MapMap, 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 = recursive_iterator(map);
+  auto rit = RecursiveIterator(map);
   std::get<3>(*rit) = 4;
   EXPECT_THAT(map[1][1][1], 4);
 }
 
-TEST(BoundRecursiveIteratorMapTest, PreIncrementAdvancesIterator) {
+TEST(RecursiveIterator_Map_Bounded, 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 = recursive_iterator(map, bounded<2>{});
+  auto rit = RecursiveIterator(map, bounded<2>{});
   EXPECT_THAT(std::get<2>(*rit), map[1][1]);
   EXPECT_THAT(std::get<2>(*++rit), map[2][2]);
   EXPECT_THAT(std::get<2>(*rit), map[2][2]);
 }
 
-TEST(BoundRecursiveIteratorMapTest, PostIncrementReturnsCopyOfPrev) {
+TEST(RecursiveIterator_Map_Bounded, 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 = recursive_iterator(map, bounded<2>{});
+  auto rit = RecursiveIterator(map, bounded<2>{});
   EXPECT_THAT(std::get<2>(*rit), map[1][1]);
   EXPECT_THAT(std::get<2>(*rit++), map[1][1]);
   EXPECT_THAT(std::get<2>(*rit), map[2][2]);
 }
 
-TEST(BoundRecursiveIteratorMapTest, IterDistanceSumOnNLayersSize) {
+TEST(RecursiveIterator_Map_Bounded, 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 = recursive_iterator(map, bounded<2>{});
+  auto rit = RecursiveIterator(map, bounded<2>{});
 
   EXPECT_THAT(ranges::distance(rit, iterator::sentinel), 3);
 }
 
-TEST(BoundRecursiveIteratorMapTest, ElementsAreUnwrappedAsATuple) {
+TEST(RecursiveIterator_Map_Bounded, ElementsAreUnwrappedAsATuple) {
   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}}}}}};
   std::vector<std::tuple<int, int, std::map<int, int>>> const expected{
@@ -96,10 +96,10 @@ TEST(BoundRecursiveIteratorMapTest, ElementsAreUnwrappedAsATuple) {
               ElementsAreArray(expected));
 }
 
-TEST(BoundedRecursiveIteratorMapTest, CanMutatePointedToData) {
+TEST(RecursiveIterator_Map_Bounded, 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 = recursive_iterator(map, bounded<2>{});
+  auto rit = RecursiveIterator(map, bounded<2>{});
   std::get<2>(*rit).clear();
   EXPECT_THAT(map[1][1], IsEmpty());
 }

+ 23 - 23
test/recursive_iterator_mixed_container_test.cxx

@@ -6,18 +6,18 @@
 #include "ranges.h"
 #include "xcode_gtest_helper.h"
 
-using iterator::recursive_iterator;
+using iterator::RecursiveIterator;
 
 using testing::ElementsAreArray;
 
-TEST(RecursiveIteratorMapVectorTest, IterDistanceIsSumOfInnerContainerSizes) {
+TEST(RecursiveIterator_MapVector, IterDistanceIsSumOfInnerContainerSizes) {
   std::map<int, std::vector<int>> const obj{{1, {1, 2}}, {2, {3, 4, 5}}};
-  auto rit = recursive_iterator(obj);
+  auto rit = RecursiveIterator(obj);
 
   EXPECT_THAT(ranges::distance(rit, iterator::sentinel), 5);
 }
 
-TEST(RecursiveIteratorMapVectorTest, ElementsAreUnwrappedAsATuple) {
+TEST(RecursiveIterator_MapVector, 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}};
@@ -26,30 +26,30 @@ TEST(RecursiveIteratorMapVectorTest, ElementsAreUnwrappedAsATuple) {
               ElementsAreArray(expected));
 }
 
-TEST(RecursiveIteratorMapVectorTest, CanMutatePointedToData) {
+TEST(RecursiveIterator_MapVector, CanMutatePointedToData) {
   std::map<int, std::vector<int>> obj{{1, {1, 2}}, {2, {3, 4, 5}}};
-  auto rit = recursive_iterator(obj);
+  auto rit = RecursiveIterator(obj);
   std::get<1>(*rit) = 6;
   EXPECT_THAT(obj[1][0], 6);
 }
 
-TEST(RecursiveIteratorMapMapVectorTest, CanMutatePointedToData) {
+TEST(RecursiveIterator_MapMapVector, CanMutatePointedToData) {
   std::map<int, std::map<int, std::vector<int>>> obj{{1, {{1, {1, 2}}}},
                                                      {2, {{1, {3, 4, 5}}}}};
-  auto rit = recursive_iterator(obj);
+  auto rit = RecursiveIterator(obj);
   std::get<2>(*rit) = 6;
   EXPECT_THAT(obj[1][1][0], 6);
 }
 
-TEST(RecursiveIteratorVectorMapTest, IterDistanceIsSumOfInnerContainerSizes) {
+TEST(RecursiveIterator_VectorMap, IterDistanceIsSumOfInnerContainerSizes) {
   std::vector<std::map<int, int>> const obj{{{1, 1}, {2, 2}},
                                             {{3, 3}, {4, 4}, {5, 5}}};
-  auto rit = recursive_iterator(obj);
+  auto rit = RecursiveIterator(obj);
 
   EXPECT_THAT(ranges::distance(rit, iterator::sentinel), 5);
 }
 
-TEST(RecursiveIteratorVectorMapTest, ElementsAreUnwrappedAsATuple) {
+TEST(RecursiveIterator_VectorMap, ElementsAreUnwrappedAsATuple) {
   std::vector<std::map<int, int>> const obj{{{1, 1}, {2, 2}},
                                             {{3, 3}, {4, 4}, {5, 5}}};
   std::vector<std::pair<int, int>> const expected{
@@ -59,24 +59,24 @@ TEST(RecursiveIteratorVectorMapTest, ElementsAreUnwrappedAsATuple) {
               ElementsAreArray(expected));
 }
 
-TEST(RecursiveIteratorVectorMapTest, CanMutatePointedToData) {
+TEST(RecursiveIterator_VectorMap, CanMutatePointedToData) {
   std::vector<std::map<int, int>> obj{{{1, 1}, {2, 2}},
                                       {{3, 3}, {4, 4}, {5, 5}}};
-  auto rit = recursive_iterator(obj);
+  auto rit = RecursiveIterator(obj);
   std::get<1>(*rit) = 6;
   EXPECT_THAT(obj[0][1], 6);
 }
 
-TEST(RecursiveIteratorMapVecMapTest, IterDistanceIsSumOfInnerContainerSizes) {
+TEST(RecursiveIterator_MapVectorMap, 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 = recursive_iterator(obj);
+  auto rit = RecursiveIterator(obj);
 
   EXPECT_THAT(ranges::distance(rit, iterator::sentinel), expected.size());
 }
 
-TEST(RecursiveIteratorMapVecMapTest, ElementsAreUnwrappedAsATuple) {
+TEST(RecursiveIterator_MapVectorMap, 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}};
@@ -85,22 +85,22 @@ TEST(RecursiveIteratorMapVecMapTest, ElementsAreUnwrappedAsATuple) {
               ElementsAreArray(expected));
 }
 
-TEST(RecursiveIteratorMapVecMapTest, CanMutatePointedToData) {
+TEST(RecursiveIterator_MapVectorMap, CanMutatePointedToData) {
   std::map<int, std::vector<std::map<int, int>>> obj{{1, {{{1, 1}, {2, 2}}}}};
-  auto rit = recursive_iterator(obj);
+  auto rit = RecursiveIterator(obj);
   std::get<2>(*rit) = 4;
   EXPECT_THAT(obj[1][0][1], 4);
 }
 
-TEST(RecursiveIteratorVecMapVecTest, IterDistanceIsSumOfInnerContainerSizes) {
+TEST(RecursiveIterator_VecMapVec, IterDistanceIsSumOfInnerContainerSizes) {
   std::vector<std::map<int, std::vector<int>>> const obj{
       {{1, {1, 2}}, {2, {3, 4, 5}}}, {{1, {3, 4}}}};
-  auto rit = recursive_iterator(obj);
+  auto rit = RecursiveIterator(obj);
 
   EXPECT_THAT(ranges::distance(rit, iterator::sentinel), 7);
 }
 
-TEST(RecursiveIteratorVecMapVecTest, ElementsAreUnwrappedAsATuple) {
+TEST(RecursiveIterator_VecMapVec, ElementsAreUnwrappedAsATuple) {
   std::vector<std::map<int, std::vector<int>>> const obj{
       {{1, {1, 2}}, {2, {3, 4, 5}}}, {{1, {3, 4}}}};
   std::vector<std::tuple<int, int>> const expected{
@@ -110,10 +110,10 @@ TEST(RecursiveIteratorVecMapVecTest, ElementsAreUnwrappedAsATuple) {
               ElementsAreArray(expected));
 }
 
-TEST(RecursiveIteratorVecMapVecTest, CanMutatePointedToData) {
+TEST(RecursiveIterator_VecMapVec, CanMutatePointedToData) {
   std::vector<std::map<int, std::vector<int>>> obj{
       {{1, {1, 2}}, {2, {3, 4, 5}}}, {{1, {3, 4}}}};
-  auto rit = recursive_iterator(obj);
+  auto rit = RecursiveIterator(obj);
   std::get<1>(*rit) = 6;
 
   EXPECT_THAT(obj[0][1][0], 6);

+ 11 - 11
test/recursive_iterator_single_level_test.cxx

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

+ 19 - 19
test/recursive_iterator_vector_test.cxx

@@ -8,35 +8,35 @@
 #include "xcode_gtest_helper.h"
 
 using iterator::bounded;
-using iterator::recursive_iterator;
+using iterator::RecursiveIterator;
 
 using testing::ElementsAreArray;
 using testing::IsEmpty;
 
-TEST(RecursiveIteratorVecTest, PreIncrementAdvancesIterator) {
+TEST(RecursiveIterator_VecVec, PreIncrementAdvancesIterator) {
   std::vector<std::vector<std::vector<int>>> const vec{{{1, 2}}, {{3}, {4, 5}}};
-  auto rit = recursive_iterator(vec);
+  auto rit = RecursiveIterator(vec);
   EXPECT_THAT(*rit, 1);
   EXPECT_THAT(*++rit, 2);
   EXPECT_THAT(*rit, 2);
 }
 
-TEST(RecursiveIteratorVecTest, PostIncrementReturnsCopyOfPrev) {
+TEST(RecursiveIterator_VecVec, PostIncrementReturnsCopyOfPrev) {
   std::vector<std::vector<std::vector<int>>> const vec{{{1, 2}}, {{3}, {4, 5}}};
-  auto rit = recursive_iterator(vec);
+  auto rit = RecursiveIterator(vec);
   EXPECT_THAT(*rit, 1);
   EXPECT_THAT(*rit++, 1);
   EXPECT_THAT(*rit, 2);
 }
 
-TEST(RecursiveIteratorVecTest, IterDistanceIsSumOfInnerContainerSizes) {
+TEST(RecursiveIterator_VecVec, IterDistanceIsSumOfInnerContainerSizes) {
   std::vector<std::vector<std::vector<int>>> const vec{{{1, 2}}, {{3}, {4, 5}}};
-  auto rit = recursive_iterator(vec);
+  auto rit = RecursiveIterator(vec);
 
   EXPECT_THAT(ranges::distance(rit, iterator::sentinel), 5);
 }
 
-TEST(RecursiveIteratorVecTest, FlattensVectorDataLikeJoinIterator) {
+TEST(RecursiveIterator_VecVec, FlattensVectorDataLikeJoinIterator) {
   std::vector<std::vector<std::vector<int>>> const vec{{{1, 2}}, {{3}, {4, 5}}};
 
   std::vector<int> const expected{1, 2, 3, 4, 5};
@@ -44,37 +44,37 @@ TEST(RecursiveIteratorVecTest, FlattensVectorDataLikeJoinIterator) {
               ElementsAreArray(expected));
 }
 
-TEST(RecursiveIteratorVecTest, CanMutatePointedToData) {
+TEST(RecursiveIterator_VecVec, CanMutatePointedToData) {
   std::vector<std::vector<std::vector<int>>> vec{{{1, 2}}, {{3}, {4, 5}}};
-  auto rit = recursive_iterator(vec);
+  auto rit = RecursiveIterator(vec);
   *rit = 6;
   EXPECT_THAT(vec[0][0][0], 6);
 }
 
-TEST(BoundedRecursiveIteratorVecTest, PreIncrementAdvancesIterator) {
+TEST(RecursiveIterator_Vec_Bounded, PreIncrementAdvancesIterator) {
   std::vector<std::vector<std::vector<int>>> const vec{{{1, 2}}, {{3}, {4, 5}}};
-  auto rit = recursive_iterator(vec, bounded<2>{});
+  auto rit = RecursiveIterator(vec, bounded<2>{});
   EXPECT_THAT(*rit, vec[0][0]);
   EXPECT_THAT(*++rit, vec[1][0]);
   EXPECT_THAT(*rit, vec[1][0]);
 }
 
-TEST(BoundedRecursiveIteratorVecTest, PostIncrementReturnsCopyOfPrev) {
+TEST(RecursiveIterator_Vec_Bounded, PostIncrementReturnsCopyOfPrev) {
   std::vector<std::vector<std::vector<int>>> const vec{{{1, 2}}, {{3}, {4, 5}}};
-  auto rit = recursive_iterator(vec, bounded<2>{});
+  auto rit = RecursiveIterator(vec, bounded<2>{});
   EXPECT_THAT(*rit, vec[0][0]);
   EXPECT_THAT(*rit++, vec[0][0]);
   EXPECT_THAT(*rit, vec[1][0]);
 }
 
-TEST(BoundedRecursiveIteratorVecTest, IterDistanceSumOnNLayersSize) {
+TEST(RecursiveIterator_Vec_Bounded, IterDistanceSumOnNLayersSize) {
   std::vector<std::vector<std::vector<int>>> const vec{{{1, 2}}, {{3}, {4, 5}}};
-  auto rit = recursive_iterator(vec, bounded<2>{});
+  auto rit = RecursiveIterator(vec, bounded<2>{});
 
   EXPECT_THAT(ranges::distance(rit, iterator::sentinel), 3);
 }
 
-TEST(BoundedRecursiveIteratorVecTest, ElementsAreUnwrappedAsATuple) {
+TEST(RecursiveIterator_Vec_Bounded, ElementsAreUnwrappedAsATuple) {
   std::vector<std::vector<std::vector<int>>> const vec{{{1, 2}}, {{3}, {4, 5}}};
 
   std::vector<std::vector<int>> const expected{{1, 2}, {3}, {4, 5}};
@@ -82,9 +82,9 @@ TEST(BoundedRecursiveIteratorVecTest, ElementsAreUnwrappedAsATuple) {
               ElementsAreArray(expected));
 }
 
-TEST(BoundedRecursiveIteratorVecTest, CanMutatePointedToData) {
+TEST(RecursiveIterator_Vec_Bounded, CanMutatePointedToData) {
   std::vector<std::vector<std::vector<int>>> vec{{{1, 2}}, {{3}, {4, 5}}};
-  auto rit = recursive_iterator(vec, bounded<2>{});
+  auto rit = RecursiveIterator(vec, bounded<2>{});
   rit->clear();
   EXPECT_THAT(vec[0][0], IsEmpty());
 }

+ 0 - 79
test/unkeyed_iterator_test.cxx

@@ -1,79 +0,0 @@
-#include "iterator/unkeyed_iterator.h"
-
-#include <map>
-#include <vector>
-
-#include "xcode_gtest_helper.h"
-
-#include "iterator/end_aware_iterator.h"
-
-using iterator::end_aware_iterator;
-using iterator::unkeyed_iterator;
-
-using testing::Ne;
-
-TEST(UnkeyedIteratorTest, IteratorOnlyReturnsValues) {
-  std::map<int, int> map{{1, 2}, {2, 3}};
-  std::vector<int> const expected{2, 3};
-  std::vector<int> const result{unkeyed_iterator{map.begin()},
-                                unkeyed_iterator{map.end()}};
-  EXPECT_THAT(result, expected);
-}
-
-TEST(UnkeyedIteratorTest, CanModifyIteratedCollectionValues) {
-  std::map<int, int> map{{1, 2}, {2, 3}};
-  unkeyed_iterator uit{map.begin()};
-  *uit = 4;
-  EXPECT_THAT(map[1], 4);
-}
-
-TEST(UnkeyedIteratorTest, PreIncrementAdvancesIterator) {
-  std::map<int, int> map{{1, 2}, {2, 3}};
-  unkeyed_iterator it(map.begin());
-  EXPECT_THAT(*it, 2);
-  EXPECT_THAT(*++it, 3);
-  EXPECT_THAT(*it, 3);
-}
-
-TEST(UnkeyedIteratorTest, PostIncrementReturnsCopyOfPrev) {
-  std::map<int, int> map{{1, 2}, {2, 3}};
-  unkeyed_iterator it(map.begin());
-  EXPECT_THAT(*it, 2);
-  EXPECT_THAT(*it++, 2);
-  EXPECT_THAT(*it, 3);
-}
-
-TEST(UnkeyedIteratorTest, PreDecrementAdvancesIterator) {
-  std::map<int, int> map{{1, 2}, {2, 3}};
-  unkeyed_iterator it(++map.begin());
-  EXPECT_THAT(*it, 3);
-  EXPECT_THAT(*--it, 2);
-  EXPECT_THAT(*it, 2);
-}
-
-TEST(UnkeyedIteratorTest, PostDecrementReturnsCopyOfPrev) {
-  std::map<int, int> map{{1, 2}, {2, 3}};
-  unkeyed_iterator it(++map.begin());
-  EXPECT_THAT(*it, 3);
-  EXPECT_THAT(*it--, 3);
-  EXPECT_THAT(*it, 2);
-}
-
-TEST(UnkeyedIteratorTest, EqualityIsPassthrough) {
-  std::map<int, int> map{{1, 2}, {2, 3}};
-  EXPECT_THAT(++unkeyed_iterator(map.begin()), unkeyed_iterator(++map.begin()));
-  EXPECT_THAT(unkeyed_iterator(map.begin()),
-              Ne(unkeyed_iterator(++map.begin())));
-}
-
-TEST(UnkeyedIteratorTest, PropagatesAtEnd) {
-  std::map<int, int> map{{1, 2}, {2, 3}};
-  unkeyed_iterator end(end_aware_iterator(map.end(), map.end()));
-  EXPECT_EQ(end, iterator::sentinel);
-}
-
-TEST(UnkeyedIteratorTest, CanPointToObject) {
-  std::map<int, int> map{{1, 2}, {2, 3}};
-  EXPECT_THAT(unkeyed_iterator(map.begin()).operator->(),
-              &(map.begin()->second));
-}

+ 78 - 0
test/values_iterator_test.cxx

@@ -0,0 +1,78 @@
+#include "iterator/values_iterator.h"
+
+#include <map>
+#include <vector>
+
+#include "xcode_gtest_helper.h"
+
+#include "iterator/end_aware_iterator.h"
+
+using iterator::EndAwareIterator;
+using iterator::ValuesIterator;
+
+using testing::Eq;
+using testing::Ne;
+
+TEST(ValuesIterator, IteratorOnlyReturnsValues) {
+  std::map<int, int> map{{1, 2}, {2, 3}};
+  std::vector<int> const expected{2, 3};
+  std::vector<int> const result{ValuesIterator{map.begin()},
+                                ValuesIterator{map.end()}};
+  EXPECT_THAT(result, expected);
+}
+
+TEST(ValuesIterator, CanModifyIteratedCollectionValues) {
+  std::map<int, int> map{{1, 2}, {2, 3}};
+  ValuesIterator uit{map.begin()};
+  *uit = 4;
+  EXPECT_THAT(map[1], 4);
+}
+
+TEST(ValuesIterator, PreIncrementAdvancesIterator) {
+  std::map<int, int> map{{1, 2}, {2, 3}};
+  ValuesIterator it(map.begin());
+  EXPECT_THAT(*it, 2);
+  EXPECT_THAT(*++it, 3);
+  EXPECT_THAT(*it, 3);
+}
+
+TEST(ValuesIterator, PostIncrementReturnsCopyOfPrev) {
+  std::map<int, int> map{{1, 2}, {2, 3}};
+  ValuesIterator it(map.begin());
+  EXPECT_THAT(*it, 2);
+  EXPECT_THAT(*it++, 2);
+  EXPECT_THAT(*it, 3);
+}
+
+TEST(ValuesIterator, PreDecrementAdvancesIterator) {
+  std::map<int, int> map{{1, 2}, {2, 3}};
+  ValuesIterator it(++map.begin());
+  EXPECT_THAT(*it, 3);
+  EXPECT_THAT(*--it, 2);
+  EXPECT_THAT(*it, 2);
+}
+
+TEST(ValuesIterator, PostDecrementReturnsCopyOfPrev) {
+  std::map<int, int> map{{1, 2}, {2, 3}};
+  ValuesIterator it(++map.begin());
+  EXPECT_THAT(*it, 3);
+  EXPECT_THAT(*it--, 3);
+  EXPECT_THAT(*it, 2);
+}
+
+TEST(ValuesIterator, EqualityIsPassthrough) {
+  std::map<int, int> map{{1, 2}, {2, 3}};
+  EXPECT_THAT(++ValuesIterator(map.begin()), ValuesIterator(++map.begin()));
+  EXPECT_THAT(ValuesIterator(map.begin()), Ne(ValuesIterator(++map.begin())));
+}
+
+TEST(ValuesIterator, PropagatesAtEnd) {
+  std::map<int, int> map{{1, 2}, {2, 3}};
+  ValuesIterator end(EndAwareIterator(map.end(), map.end()));
+  EXPECT_THAT(end, Eq(iterator::sentinel));
+}
+
+TEST(ValuesIterator, CanPointToObject) {
+  std::map<int, int> map{{1, 2}, {2, 3}};
+  EXPECT_THAT(ValuesIterator(map.begin()).operator->(), &(map.begin()->second));
+}

+ 23 - 23
test/zip_iterator_test.cxx

@@ -14,7 +14,7 @@
 
 #include "xcode_gtest_helper.h"
 
-using iterator::zip_iterator;
+using iterator::ZipIterator;
 
 using testing::Eq;
 using testing::Ge;
@@ -24,64 +24,64 @@ using testing::Lt;
 using testing::Ne;
 using testing::StaticAssertTypeEq;
 
-TEST(ZipIteratorTest, CategoryIsMostRestrictiveOfTypes) {
+TEST(ZipIterator, CategoryIsMostRestrictiveOfTypes) {
   std::vector<int> rnd{1, 2, 3};
   std::vector<std::string> ss{"A", "B", "C"};
   std::list<int> bid{1, 2, 3};
   std::forward_list<int> fwd{1, 2, 3};
   {
-    zip_iterator zit(rnd.begin(), ss.begin());
+    ZipIterator zit(rnd.begin(), ss.begin());
     StaticAssertTypeEq<std::iterator_traits<decltype(zit)>::iterator_category,
                        std::random_access_iterator_tag>();
   }
   {
-    zip_iterator zit(rnd.begin(), bid.begin());
+    ZipIterator zit(rnd.begin(), bid.begin());
     StaticAssertTypeEq<std::iterator_traits<decltype(zit)>::iterator_category,
                        std::bidirectional_iterator_tag>();
   }
   {
-    zip_iterator zit(rnd.begin(), fwd.begin());
+    ZipIterator zit(rnd.begin(), fwd.begin());
     StaticAssertTypeEq<std::iterator_traits<decltype(zit)>::iterator_category,
                        std::forward_iterator_tag>();
   }
   {
-    zip_iterator zit(bid.begin(), fwd.begin());
+    ZipIterator zit(bid.begin(), fwd.begin());
     StaticAssertTypeEq<std::iterator_traits<decltype(zit)>::iterator_category,
                        std::forward_iterator_tag>();
   }
 }
 
-TEST(ZipIteratorTest, CanCombineParallelObjects) {
+TEST(ZipIterator, CanCombineParallelObjects) {
   std::vector<int> is{1, 2, 3};
   std::vector<std::string> ss{"A", "B", "C"};
-  zip_iterator zit(is.begin(), ss.begin());
+  ZipIterator zit(is.begin(), ss.begin());
   EXPECT_THAT(std::get<0>(*zit), 1);
   EXPECT_THAT(std::get<1>(*zit), "A");
 }
 
-TEST(ZipIteratorTest, AdvancingMovesAllElements) {
+TEST(ZipIterator, AdvancingMovesAllElements) {
   std::vector<int> is{1, 2, 3};
   std::vector<std::string> ss{"A", "B", "C"};
-  zip_iterator zit(is.begin(), ss.begin());
+  ZipIterator zit(is.begin(), ss.begin());
   zit++;
   EXPECT_THAT(std::get<0>(*zit), 2);
   EXPECT_THAT(std::get<1>(*zit), "B");
 }
 
-TEST(ZipIteratorTest, CanDecrement) {
+TEST(ZipIterator, CanDecrement) {
   std::vector<int> is{1, 2, 3};
   std::vector<std::string> ss{"A", "B", "C"};
-  zip_iterator zit(is.begin(), ss.begin());
+  ZipIterator zit(is.begin(), ss.begin());
   ++zit;
   zit--;
   EXPECT_THAT(std::get<0>(*zit), 1);
   EXPECT_THAT(std::get<1>(*zit), "A");
 }
 
-TEST(ZipIteratorTest, CanMoveByAnyAmount) {
+TEST(ZipIterator, CanMoveByAnyAmount) {
   std::vector<int> is{1, 2, 3};
   std::vector<std::string> ss{"A", "B", "C"};
-  zip_iterator zit(is.begin(), ss.begin());
+  ZipIterator zit(is.begin(), ss.begin());
   zit = 2 + zit;
   EXPECT_THAT(std::get<0>(*zit), 3);
   EXPECT_THAT(std::get<1>(*zit), "C");
@@ -90,28 +90,28 @@ TEST(ZipIteratorTest, CanMoveByAnyAmount) {
   EXPECT_THAT(std::get<1>(*zit), "A");
 }
 
-TEST(ZipIteratorTest, CanMarkDistance) {
+TEST(ZipIterator, CanMarkDistance) {
   std::vector<int> is{1, 2, 3};
   std::vector<std::string> ss{"A", "B", "C"};
-  zip_iterator zit(is.begin(), ss.begin());
-  zip_iterator zend(is.end(), ss.end());
+  ZipIterator zit(is.begin(), ss.begin());
+  ZipIterator zend(is.end(), ss.end());
   EXPECT_THAT(zend - zit, 3);
 }
 
-TEST(ZipIteratorTest, CanRandomAccess) {
+TEST(ZipIterator, CanRandomAccess) {
   std::vector<int> is{1, 2, 3};
   std::vector<std::string> ss{"A", "B", "C"};
-  zip_iterator zit(is.begin(), ss.begin());
+  ZipIterator zit(is.begin(), ss.begin());
   EXPECT_THAT(std::get<0>(zit[1]), 2);
   EXPECT_THAT(std::get<1>(zit[1]), "B");
 }
 
-TEST(ZipIteratorTest, CanCompareIterators) {
+TEST(ZipIterator, CanCompareIterators) {
   std::vector<int> is{1, 2, 3};
   std::vector<std::string> ss{"A", "B", "C"};
-  zip_iterator const zit(is.begin(), ss.begin());
-  zip_iterator const zend(is.end(), ss.end());
-  EXPECT_THAT(zit, Eq(zip_iterator(is.begin(), ss.begin())));
+  ZipIterator const zit(is.begin(), ss.begin());
+  ZipIterator const zend(is.end(), ss.end());
+  EXPECT_THAT(zit, Eq(ZipIterator(is.begin(), ss.begin())));
   EXPECT_THAT(zit, Ne(zend));
   EXPECT_THAT(zit, Lt(zend));
   EXPECT_THAT(zit, Le(zend));