recursive_iterator.hpp 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378
  1. //
  2. // recursive_iterator.hpp
  3. // iterator
  4. //
  5. // Created by Sam Jaffe on 2/17/17.
  6. //
  7. #pragma once
  8. #include "iterator_fwd.hpp"
  9. #include "end_aware_iterator.hpp"
  10. namespace iterator { namespace detail {
  11. struct terminal_layer_tag_t;
  12. struct continue_layer_tag_t;
  13. /**
  14. * @class recursive_iterator_base
  15. * @breif A thin wrapper around end_aware_iterator for the purposes of template metaprogramming.
  16. */
  17. template <typename Iterator, typename = void>
  18. class recursive_iterator_base : public end_aware_iterator<Iterator> {
  19. public:
  20. using super = end_aware_iterator<Iterator>;
  21. protected:
  22. using recursive_category = terminal_layer_tag_t;
  23. public:
  24. using super::super;
  25. recursive_iterator_base() = default;
  26. operator super() const { return *this; }
  27. protected:
  28. typename super::reference get() const { return super::operator*(); }
  29. };
  30. /**
  31. * @class recursive_iterator_base
  32. * @brief An SFINAE specialization of recursive_iterator_base for associative containers
  33. *
  34. * Because it is possible for recursive iterator to step over multiple layers
  35. * of associative containers, the return type is made into a tuple, so that
  36. * the caller does not need to write something like `it->second.second.second'.
  37. * Instead, the return type is a tuple of references, so that the caller can
  38. * write code like `std::get<3>(*it)'.
  39. *
  40. * For example, the ref type for std::map<int, std::map<float, double> >
  41. * with this would be std::tuple<int const&, float const&, double &>.
  42. */
  43. template <typename Iterator>
  44. class recursive_iterator_base<Iterator, typename std::enable_if<std::is_const<typename end_aware_iterator<Iterator>::value_type::first_type>::value>::type> : public end_aware_iterator<Iterator> {
  45. public:
  46. using super = end_aware_iterator<Iterator>;
  47. using first_type = decltype((std::declval<Iterator>()->first));
  48. using second_type = decltype((std::declval<Iterator>()->second));
  49. protected:
  50. using recursive_category = continue_layer_tag_t;
  51. public:
  52. using value_type = std::tuple<first_type, second_type>;
  53. using reference = std::tuple<first_type &, second_type &>;
  54. public:
  55. using super::super;
  56. recursive_iterator_base() = default;
  57. operator super() const { return *this; }
  58. protected:
  59. /**
  60. * An alternative function to operator*(), which allows single layer
  61. * recursive iterators (on associative containers) to return the
  62. * underlying value/reference type, and nested containers to propogate
  63. * a tuple or a pair as necessary.
  64. */
  65. reference get() const {
  66. auto & pair = super::operator*();
  67. return std::tie(pair.first, pair.second);
  68. }
  69. };
  70. /**
  71. * @class recursive_iterator_layer
  72. * @breif A single layer for recursing down a nested collection. Represents non-associative containers.
  73. *
  74. * Provides dispatch/overloading for types and functions of recursive_iterator
  75. * chains to resolve ambiguous typedefs and operators.
  76. *
  77. * @see recursive_iterator_impl
  78. * @see bounded_recursive_iterator_impl
  79. * @param Iterator The underlying iterator type of the layer
  80. * @param RecursiveIterator_NextLayer The next layer, either a recursive_iterator_impl, or a bounded_recursive_iterator_impl
  81. */
  82. template <typename Iterator, typename RecursiveIterator_NextLayer>
  83. class recursive_iterator_layer :
  84. public recursive_iterator_base< Iterator >,
  85. public RecursiveIterator_NextLayer {
  86. public:
  87. using super = RecursiveIterator_NextLayer;
  88. using layer = recursive_iterator_base< Iterator >;
  89. protected:
  90. using recursive_category = continue_layer_tag_t;
  91. public:
  92. using value_type = typename super::value_type;
  93. using reference = typename super::reference;
  94. using pointer = typename super::pointer;
  95. using difference_type = typename super::difference_type;
  96. using iterator_category = std::forward_iterator_tag;
  97. public:
  98. recursive_iterator_layer() = default;
  99. recursive_iterator_layer(layer v) : recursive_iterator_layer() {
  100. assign(v);
  101. update();
  102. }
  103. template <typename OIter, typename Rec>
  104. recursive_iterator_layer(recursive_iterator_layer<OIter, Rec> const & other) : layer(static_cast<recursive_iterator_base<OIter>const&>(other)), super(static_cast<Rec const&>(other)) {}
  105. template <typename OIter, typename... Iterators>
  106. recursive_iterator_layer(in_place_t, OIter it, Iterators && ...iter)
  107. : layer(it), super(in_place, iter...) {
  108. update();
  109. }
  110. reference operator*() const {
  111. return super::get();
  112. }
  113. pointer operator->() const {
  114. return super::operator->();
  115. }
  116. bool operator==(recursive_iterator_layer const & other) const {
  117. return layer::operator==(other) && super::operator==(other);
  118. }
  119. protected:
  120. reference get() const { return operator*(); }
  121. /**
  122. * Advance the iterator step. If the next layer has reached the end, then
  123. * we advance this iterator until it reaches either its own end, or a
  124. * non-empty subcollection to start iterating over.
  125. */
  126. void next() {
  127. super::next();
  128. update();
  129. }
  130. /**
  131. * Update the underlying iterator and propogate updates down the chain so
  132. * that if there is data available, the iterator is in a dereferencable
  133. * state.
  134. */
  135. void assign(layer v) {
  136. static_cast<layer&>(*this) = v;
  137. if (!v.done()) {
  138. super::assign(make_end_aware_iterator(*v));
  139. }
  140. }
  141. void update() {
  142. layer & self = static_cast<layer&>(*this);
  143. while ( super::done() && !(++self).done() ) {
  144. super::assign(make_end_aware_iterator(*self));
  145. }
  146. }
  147. bool done() const { return layer::done(); }
  148. };
  149. /**
  150. * @class next_layer_type
  151. * @breif A template metaprogramming type for unifying associative and non-associative containers.
  152. */
  153. template <typename V, typename Tag>
  154. struct next_layer_type { using type = std::tuple<V>; };
  155. template <typename V>
  156. struct next_layer_type<V, continue_layer_tag_t> { using type = V; };
  157. /**
  158. * @class flatten_iterator_layer
  159. * @breif A single layer for recursing down a nested collection. Represents associative containers.
  160. *
  161. * @copydoc recursive_iterator_layer
  162. */
  163. template <typename Iterator, typename RecursiveIterator_NextLayer>
  164. class flatten_iterator_layer :
  165. public recursive_iterator_base< Iterator >,
  166. public RecursiveIterator_NextLayer {
  167. public:
  168. using super = RecursiveIterator_NextLayer;
  169. using layer = recursive_iterator_base< Iterator >;
  170. using key_type = typename std::tuple_element<0, typename layer::value_type>::type;
  171. protected:
  172. using recursive_category = continue_layer_tag_t;
  173. using next_value_type = typename next_layer_type<typename super::value_type, typename super::recursive_category>::type;
  174. using next_reference = typename next_layer_type<typename super::reference, typename super::recursive_category>::type;
  175. public:
  176. using value_type = decltype(std::tuple_cat(std::make_tuple(std::declval<key_type>()),
  177. std::declval<next_value_type>()));
  178. using reference = decltype(std::tuple_cat(std::tie(std::declval<key_type>()),
  179. std::declval<next_reference>()));
  180. using pointer = void;
  181. using difference_type = typename super::difference_type;
  182. using iterator_category = std::forward_iterator_tag;
  183. public:
  184. flatten_iterator_layer() = default;
  185. flatten_iterator_layer(layer v) : flatten_iterator_layer() {
  186. assign(v);
  187. update();
  188. }
  189. template <typename OIter, typename Rec>
  190. flatten_iterator_layer(flatten_iterator_layer<OIter, Rec> const & other) : layer(static_cast<recursive_iterator_base<OIter>const&>(other)), super(static_cast<Rec const&>(other)) {}
  191. template <typename OIter, typename... Iterators>
  192. flatten_iterator_layer(in_place_t, OIter it, Iterators && ...iter)
  193. : layer(it), super(in_place, iter...) {
  194. update();
  195. }
  196. /**
  197. * @breif Concatenate the key in this layer, with the dereferenced data from the next.
  198. *
  199. * Due to the use of the next_layer_type metaprogramming, a type such as
  200. * std::map<K, std::vector<std::tuple<T1, T2, T3>>> would return a reference
  201. * of type std::tuple<K const &, std::tuple<T1, T2, T3>&>, preserving
  202. * sub-aggregates of pair/tuple type. Similarly, forward_as_tuple means
  203. * even a key-type of pair/tuple will not be unwrapped.
  204. */
  205. reference operator*() const {
  206. return std::tuple_cat(std::forward_as_tuple(std::get<0>(layer::get())),
  207. next_reference(super::get()));
  208. }
  209. /**
  210. * Unimplemented because we return an inline constructed type, and tuple
  211. * can only be accessed through std::get anyway.
  212. */
  213. pointer operator->() const;
  214. bool operator==(flatten_iterator_layer const & other) const {
  215. return layer::operator==(other) && super::operator==(other);
  216. }
  217. protected:
  218. reference get() const { return operator*(); }
  219. /**
  220. * @copydoc recursive_iterator_layer::next
  221. */
  222. void next() {
  223. super::next();
  224. update();
  225. }
  226. void update() {
  227. layer & self = static_cast<layer&>(*this);
  228. while ( super::done() && !(++self).done() ) {
  229. super::assign(make_end_aware_iterator(self->second));
  230. }
  231. }
  232. /**
  233. * @copydoc recursive_iterator_layer::assign
  234. */
  235. void assign(layer v) {
  236. static_cast<layer&>(*this) = v;
  237. if ( !v.done() ) {
  238. super::assign(make_end_aware_iterator(v->second));
  239. }
  240. }
  241. bool done() const { return layer::done(); }
  242. };
  243. } }
  244. #include "recursive_iterator_meta.hpp"
  245. namespace iterator {
  246. /**
  247. * @class recursive_iterator
  248. * @breif An iterator type for nested collections, allowing you to treat it as a single-layer collection.
  249. *
  250. * In order to provide a simple interface, if an associative container is used
  251. * in the chain, the type returned by operator*() is a tuple. If multiple
  252. * associative containers are nested, then the tuple will be of the form
  253. * std::tuple<key1, key2, ..., keyN, value>. To avoid copies, and allow
  254. * editting of underlying values, the tuple contains references.
  255. *
  256. * @param Iterator The iterator type of the top-level collection.
  257. */
  258. template <typename Iterator>
  259. class recursive_iterator : public detail::recursive_iterator_impl< Iterator > {
  260. public:
  261. using super = detail::recursive_iterator_impl< Iterator >;
  262. public:
  263. using super::super;
  264. recursive_iterator() = default;
  265. template <typename... Iterators>
  266. recursive_iterator(in_place_t, Iterators && ...iter) : super(in_place, iter...) {}
  267. recursive_iterator & operator++() {
  268. (void) super::next();
  269. return *this;
  270. }
  271. recursive_iterator operator++(int) {
  272. recursive_iterator tmp{*this};
  273. (void) super::next();
  274. return tmp;
  275. }
  276. bool operator!=(recursive_iterator const & other) { return !(super::operator==(other)); }
  277. };
  278. /**
  279. * @class recursive_iterator_n
  280. * @copydoc recursive_iterator
  281. * This object has bounded recursive depth, so that it can be used to get
  282. * sub-collections, which may be used in other functions.
  283. *
  284. * For Example:
  285. * @code
  286. * using map_type = std::map<std::string, std::map<std::string, std::vector<Data> > >;
  287. * ...
  288. * recursive_iterator_n<map_type::iterator, 2> iter{ ... };
  289. * std::vector<Data> & data = std::get<2>(*iter);
  290. * reload_data_from_file( std::get<1>(*iter), data );
  291. * @endcode
  292. *
  293. * @param N The maximum depth to recurse into the object
  294. */
  295. template <typename Iterator, std::size_t N>
  296. class recursive_iterator_n : public detail::bounded_recursive_iterator_impl< Iterator, 1, N > {
  297. public:
  298. using super = detail::bounded_recursive_iterator_impl< Iterator, 1, N >;
  299. public:
  300. using super::super;
  301. recursive_iterator_n() = default;
  302. template <typename... Iterators>
  303. recursive_iterator_n(in_place_t, Iterators && ...iter) : super(in_place, iter...) {}
  304. recursive_iterator_n & operator++() {
  305. (void) super::next();
  306. return *this;
  307. }
  308. recursive_iterator_n operator++(int) {
  309. recursive_iterator_n tmp{*this};
  310. (void) super::next();
  311. return tmp;
  312. }
  313. bool operator!=(recursive_iterator_n const & other) { return !(super::operator==(other)); }
  314. };
  315. }
  316. namespace std {
  317. template <std::size_t I, typename It>
  318. auto get(::iterator::recursive_iterator<It> const & iter) -> typename ::iterator::detail::accessor<I, ::iterator::recursive_iterator<It>>::type {
  319. return iter;
  320. }
  321. }
  322. template <typename Iter0, typename... Iters>
  323. auto make_recursive_iterator(iterator::end_aware_iterator<Iter0> it, Iters &&... iters) -> iterator::recursive_iterator<Iter0> {
  324. return { iterator::in_place, it, iters... };
  325. }
  326. template <typename C>
  327. auto make_recursive_iterator(C & collect) -> iterator::recursive_iterator<decltype(std::begin(collect))> {
  328. return { make_end_aware_iterator(collect)};
  329. }
  330. template <typename C>
  331. auto make_recursive_iterator(C const & collect) -> iterator::recursive_iterator<decltype(std::begin(collect))> {
  332. return { make_end_aware_iterator(collect) };
  333. }
  334. template <std::size_t Max, typename C>
  335. auto make_recursive_iterator(C & collect) -> iterator::recursive_iterator_n<decltype(std::begin(collect)), Max> {
  336. return { make_end_aware_iterator(collect) };
  337. }
  338. template <std::size_t Max, typename C>
  339. auto make_recursive_iterator(C const & collect) -> iterator::recursive_iterator_n<decltype(std::begin(collect)), Max> {
  340. return { make_end_aware_iterator(collect) };
  341. }