recursive_iterator.h 6.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211
  1. //
  2. // recursive_iterator.h
  3. // iterator
  4. //
  5. // Created by Sam Jaffe on 2/17/17.
  6. //
  7. #pragma once
  8. #include <string>
  9. #include <tuple>
  10. #include <utility>
  11. #include <iterator/detail/recursive_traits.h>
  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::recursive {
  17. struct unbounded {
  18. template <typename It>
  19. static constexpr recursion_type const value = iter_typeclass<It>;
  20. using next = unbounded;
  21. static constexpr size_t size = std::numeric_limits<size_t>::max();
  22. };
  23. template <size_t N, size_t I> struct bounded {
  24. template <typename It>
  25. static constexpr recursion_type const value =
  26. I == N ? recursion_type::END : iter_typeclass<It>;
  27. using next = std::conditional_t<I == N, void, bounded<N, I + 1>>;
  28. static constexpr size_t size = N;
  29. };
  30. template <typename It, typename Bnd = unbounded,
  31. recursion_type = Bnd::template value<It>>
  32. struct tuple;
  33. template <typename It, typename Bnd>
  34. struct tuple<It, Bnd, recursion_type::END> {
  35. using iter = std::tuple<end_aware_iterator<It>>;
  36. decltype(auto) get(It iter) const {
  37. if constexpr (associative_value<std::iter_value_t<It>>) {
  38. return std::tie(iter->first, iter->second);
  39. } else {
  40. return std::tie(*iter);
  41. }
  42. }
  43. };
  44. template <typename... Ts>
  45. using tuple_cat_t = decltype(std::tuple_cat(VAL(Ts)...));
  46. template <typename It, typename Bnd>
  47. struct tuple<It, Bnd, recursion_type::THRU> {
  48. using next = decltype(std::begin(*VAL(It)));
  49. using iter = tuple_cat_t<std::tuple<end_aware_iterator<It>>,
  50. typename tuple<next, typename Bnd::next>::iter>;
  51. auto get(It) const { return std::make_tuple(); }
  52. };
  53. template <typename It, typename Bnd>
  54. struct tuple<It, Bnd, recursion_type::ASSOC> {
  55. using next = decltype(std::begin(VAL(It)->second));
  56. using iter = tuple_cat_t<std::tuple<end_aware_iterator<It>>,
  57. typename tuple<next, typename Bnd::next>::iter>;
  58. auto get(It iter) const { return std::tie(iter->first); };
  59. };
  60. /**
  61. * @brief An iterator type for nested collections, allowing you to treat it as
  62. * a single-layer collection.
  63. *
  64. * In order to provide a simple interface, if an associative container is used
  65. * in the chain, the type returned by operator*() is a tuple. If multiple
  66. * associative containers are nested, then the tuple will be of the form
  67. * std::tuple<key1, key2, ..., keyN, value>. To avoid copies, and allow
  68. * editting of underlying values, the tuple contains references.
  69. *
  70. * @tparam It The iterator type of the top-level collection.
  71. * @tparam Bnd The bounding type, representing how many layers this iterator
  72. * is willing to delve in the parent object.
  73. */
  74. template <typename It, typename Bnd>
  75. class rimpl : public facade<rimpl<It, Bnd>> {
  76. public:
  77. using sentinel_type = sentinel_t;
  78. using iters_t = typename tuple<It, Bnd>::iter;
  79. static constexpr size_t n_iters =
  80. std::tuple_size_v<typename tuple<It, Bnd>::iter>;
  81. static constexpr size_t size = std::min(n_iters, Bnd::size);
  82. private:
  83. iters_t impl_;
  84. public:
  85. rimpl() = default;
  86. rimpl(end_aware_iterator<It> iter) { assign<0>(iter); }
  87. template <typename Ot>
  88. rimpl(end_aware_iterator<Ot> other) : rimpl(end_aware_iterator<It>(other)) {}
  89. template <typename Ot>
  90. rimpl(rimpl<Ot, Bnd> other) : rimpl(end_aware_iterator<Ot>(other)) {}
  91. template <typename T> operator end_aware_iterator<T>() const {
  92. return std::get<end_aware_iterator<T>>(impl_);
  93. }
  94. decltype(auto) dereference() const {
  95. // Special Case Handling for circumstances where at least everything up to
  96. // the deepest nested container is non-associative. In this case, we don't
  97. // want to transmute our single element/association into a tuple, since
  98. // there's no benefit from that.
  99. if constexpr (std::tuple_size_v<decltype(this->build_tuple())> == 1) {
  100. return *std::get<size - 1>(impl_);
  101. } else {
  102. return build_tuple();
  103. }
  104. }
  105. void increment() { increment_i(); }
  106. bool at_end() const { return std::get<0>(impl_).at_end(); }
  107. bool equal_to(rimpl const & other) const { return impl_ == other.impl_; }
  108. // Used by std::get, don't use elsewhere...
  109. auto const & impl() const { return impl_; }
  110. private:
  111. template <size_t I = size - 1> bool increment_i() {
  112. auto & iter = std::get<I>(impl_);
  113. if (iter.at_end()) { return false; } // Make sure we don't go OOB
  114. ++iter;
  115. if constexpr (I > 0) {
  116. while (iter.at_end() && increment_i<I - 1>()) {
  117. assign<I>(*std::get<I - 1>(impl_));
  118. }
  119. }
  120. return !iter.at_end();
  121. }
  122. template <size_t I> decltype(auto) get() const {
  123. auto it = std::get<I>(impl_);
  124. // In the case of a bounded recursive iterator, I need to ensure that the
  125. // effectively terminal iterator is treated as such even if there is still
  126. // iteration to be had.
  127. if constexpr (I == size - 1) {
  128. return tuple<decltype(it), unbounded, recursion_type::END>{}.get(it);
  129. } else {
  130. return tuple<decltype(it)>{}.get(it);
  131. }
  132. }
  133. template <size_t... Is>
  134. decltype(auto) build_tuple(std::index_sequence<Is...>) const {
  135. return std::tuple_cat(get<Is>()...);
  136. }
  137. decltype(auto) build_tuple() const {
  138. return build_tuple(std::make_index_sequence<size>());
  139. }
  140. template <size_t I, typename C> void assign(end_aware_iterator<C> it) {
  141. std::get<I>(impl_) = it;
  142. if constexpr (I < size - 1) {
  143. if (!it.at_end()) { assign<I + 1>(*it); }
  144. }
  145. }
  146. template <size_t I, typename C> void assign(C && collection) {
  147. assign<I>(end_aware_iterator(std::forward<C>(collection)));
  148. }
  149. template <size_t I, typename K, typename V>
  150. void assign(std::pair<K const, V> const & pair) {
  151. assign<I>(pair.second);
  152. }
  153. template <size_t I, typename K, typename V>
  154. void assign(std::pair<K const, V> & pair) {
  155. assign<I>(pair.second);
  156. }
  157. };
  158. }
  159. MAKE_ITERATOR_FACADE_TYPEDEFS_T(::iterator::recursive::rimpl);
  160. namespace std {
  161. template <std::size_t I, typename It>
  162. auto get(::iterator::recursive_iterator<It> const & iter) {
  163. return ::std::get<I>(iter.impl());
  164. }
  165. template <std::size_t I, typename It, std::size_t N>
  166. auto get(::iterator::recursive_iterator_n<It, N> const & iter) {
  167. static_assert(I < N, "Cannot get past bounding level");
  168. return ::std::get<I>(iter.impl());
  169. }
  170. }
  171. template <typename C> auto make_recursive_iterator(C && collect) {
  172. return iterator::recursive_iterator<iterator::iterator_t<C>>(collect);
  173. }
  174. template <std::size_t Max, typename C>
  175. auto make_recursive_iterator(C && collect) {
  176. return iterator::recursive_iterator_n<iterator::iterator_t<C>, Max>(
  177. collect);
  178. }
  179. #include <iterator/detail/undef.h>