recursive_iterator.hpp 14 KB

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