recursive_iterator.h 7.2 KB

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