recursive_iterator.h 7.1 KB

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