recursive_iterator.h 6.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204
  1. //
  2. // recursive_iterator.h
  3. // iterator
  4. //
  5. // Created by Sam Jaffe on 2/17/17.
  6. //
  7. #pragma once
  8. #include <ranges>
  9. #include <tuple>
  10. #include <utility>
  11. #include <iterator/concepts.h>
  12. #include <iterator/detail/projection_tuple.h>
  13. #include <iterator/detail/recursive_expander.h>
  14. #include <iterator/end_aware_iterator.h>
  15. #include <iterator/facade.h>
  16. #include <iterator/forwards.h>
  17. #include <iterator/detail/macro.h>
  18. namespace iterator {
  19. template <typename Tuple, typename Projs, typename Indices>
  20. class recursive_iterator_base;
  21. template <typename... It, typename... Projs, size_t... Is>
  22. class recursive_iterator_base<std::tuple<It...>, detail::Projections<Projs...>,
  23. std::index_sequence<Is...>>
  24. : public std::tuple<It...>, private detail::Projections<Projs...> {
  25. public:
  26. static constexpr size_t LastIndex = sizeof...(It) - 1;
  27. template <size_t I>
  28. using iterator_type = std::tuple_element_t<I, std::tuple<It...>>;
  29. template <size_t I> using value_type = std::iter_value_t<iterator_type<I>>;
  30. public:
  31. template <typename T> operator end_aware_iterator<T>() const {
  32. return std::get<end_aware_iterator<T>>(*this);
  33. }
  34. decltype(auto) dereference() const {
  35. auto rval = std::tuple_cat(get<Is>()...);
  36. // Special Case Handling for circumstances where at least everything up to
  37. // the deepest nested container is non-associative. In this case, we don't
  38. // want to transmute our single element/association into a tuple, since
  39. // there's no benefit from that.
  40. if constexpr (std::tuple_size_v<decltype(rval)> == 1) {
  41. return std::get<0>(rval); // May be a reference
  42. } else {
  43. return rval; // Tuple-of-references
  44. }
  45. }
  46. void increment() { increment<>(); }
  47. bool at_end() const { return std::get<0>(*this).at_end(); }
  48. bool equal_to(recursive_iterator_base const & other) const {
  49. return *this == other;
  50. }
  51. protected:
  52. recursive_iterator_base() = default;
  53. recursive_iterator_base(iterator_type<0> iter, Projs... projs)
  54. : detail::Projections<Projs...>(projs...) {
  55. assign<0>(iter);
  56. }
  57. private:
  58. template <size_t I = LastIndex> bool increment() {
  59. auto & iter = std::get<I>(*this);
  60. if (iter.at_end()) { return false; } // Make sure we don't go OOB
  61. ++iter;
  62. if constexpr (I > 0) {
  63. while (iter.at_end() && increment<I - 1>()) {
  64. assign<I>(*std::get<I - 1>(*this));
  65. }
  66. }
  67. return !iter.at_end();
  68. }
  69. template <size_t I> decltype(auto) get() const {
  70. auto iter = std::get<I>(*this);
  71. if constexpr (I + 1 == sizeof...(It)) {
  72. auto && rval = (*this)(*iter, std::integral_constant<size_t, I>{});
  73. if constexpr (Assoc<std::decay_t<decltype(rval)>>) {
  74. // Needed for tuple-cat to preserve references
  75. return std::tie(rval.first, rval.second);
  76. } else {
  77. return std::tie(rval); // Cannot wrap tie(pair) and expect it to work
  78. }
  79. } else if constexpr (Assoc<value_type<I>>) {
  80. return std::tie(iter->first);
  81. } else {
  82. return std::make_tuple();
  83. }
  84. }
  85. template <size_t I, typename T> void assign(end_aware_iterator<T> it) {
  86. std::get<I>(*this) = it;
  87. if constexpr (I < LastIndex) {
  88. if (!it.at_end()) {
  89. assign<I + 1>((*this)(*it, std::integral_constant<size_t, I>{}));
  90. }
  91. }
  92. }
  93. template <size_t I, typename T> void assign(T && value) {
  94. if constexpr (Range<T>) {
  95. assign<I>(end_aware_iterator(std::forward<T>(value)));
  96. } else {
  97. assign<I>(std::get<1>(value));
  98. }
  99. }
  100. };
  101. template <typename It, typename MaxDepth,
  102. typename Projs = detail::Projections<>>
  103. struct recursive_iterator_helper {
  104. static typename detail::ProjectionExpander<It, Projs>::type const & _projs;
  105. using Projections = decltype(detail::Projections(_projs));
  106. using iterator_tuple =
  107. typename detail::RecursiveExpander<It, Projections, MaxDepth>::type;
  108. static constexpr auto extent = std::tuple_size_v<iterator_tuple>;
  109. using indices = decltype(std::make_index_sequence<extent>());
  110. using type = recursive_iterator_base<iterator_tuple, Projections, indices>;
  111. };
  112. /**
  113. * @brief An iterator type for nested collections, allowing you to treat it as
  114. * a single-layer collection.
  115. *
  116. * In order to provide a simple interface, if an associative container is used
  117. * in the chain, the type returned by operator*() is a tuple. If multiple
  118. * associative containers are nested, then the tuple will be of the form
  119. * std::tuple<key1, key2, ..., keyN, value>. To avoid copies, and allow
  120. * editting of underlying values, the tuple contains references.
  121. *
  122. * @tparam It The iterator type of the top-level collection.
  123. * @tparam MaxDepth The bounding type, representing how many layers this
  124. * iterator is willing to delve in the parent object.
  125. */
  126. template <typename It, typename MaxDepth>
  127. class recursive_iterator : public recursive_iterator_helper<It, MaxDepth>::type,
  128. public facade<recursive_iterator<It, MaxDepth>> {
  129. public:
  130. using sentinel_type = sentinel_t;
  131. public:
  132. recursive_iterator() = default;
  133. explicit recursive_iterator(Range auto & range, MaxDepth = {})
  134. : recursive_iterator(end_aware_iterator(range)) {}
  135. explicit recursive_iterator(end_aware_iterator<It> iter, MaxDepth = {})
  136. : recursive_iterator::recursive_iterator_base(iter) {}
  137. template <typename Ot>
  138. explicit recursive_iterator(end_aware_iterator<Ot> other, MaxDepth = {})
  139. : recursive_iterator(end_aware_iterator<It>(other)) {}
  140. template <typename Ot>
  141. explicit recursive_iterator(recursive_iterator<Ot, MaxDepth> other)
  142. : recursive_iterator(end_aware_iterator<Ot>(other)) {}
  143. };
  144. template <typename Range, typename MaxDepth>
  145. recursive_iterator(Range &, MaxDepth)
  146. -> recursive_iterator<iterator_t<Range>, MaxDepth>;
  147. template <typename Range>
  148. recursive_iterator(Range &) -> recursive_iterator<iterator_t<Range>, unbounded>;
  149. } // namespace iterator
  150. namespace std {
  151. template <size_t I, typename It, typename MaxDepth>
  152. auto get(::iterator::recursive_iterator<It, MaxDepth> const & iter) {
  153. using return_type = std::decay_t<decltype(iter)>::template iterator_type<I>;
  154. return static_cast<return_type>(iter);
  155. }
  156. } // namespace std
  157. namespace iterator::views {
  158. template <size_t N>
  159. struct recursive_n_fn : std::ranges::range_adaptor_closure<recursive_n_fn<N>> {
  160. template <std::ranges::range Rng> auto operator()(Rng && rng) const {
  161. auto begin = recursive_iterator(std::forward<Rng>(rng), bounded<N>{});
  162. return std::ranges::subrange(begin, decltype(begin)());
  163. }
  164. };
  165. struct recursive_fn : std::ranges::range_adaptor_closure<recursive_fn> {
  166. template <std::ranges::range Rng> auto operator()(Rng && rng) const {
  167. auto begin = recursive_iterator(std::forward<Rng>(rng));
  168. return std::ranges::subrange(begin, decltype(begin)());
  169. }
  170. };
  171. template <size_t N> constexpr recursive_n_fn<N> recursive_n{};
  172. constexpr recursive_fn recursive;
  173. } // namespace iterator::views
  174. #include <iterator/detail/undef.h>