recursive_iterator.hpp 20 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503
  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 {
  11. namespace detail {
  12. struct terminal_layer_tag_t;
  13. struct continue_layer_tag_t;
  14. /**
  15. * @class recursive_iterator_base
  16. * @breif 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. private:
  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() = default;
  27. operator super() const { return *this; }
  28. protected:
  29. typename super::reference get() { return super::operator*(); }
  30. };
  31. /**
  32. * @class recursive_iterator_base
  33. * @brief An SFINAE specialization of recursive_iterator_base for associative containers
  34. *
  35. * Because it is possible for recursive iterator to step over multiple layers
  36. * of associative containers, the return type is made into a tuple, so that
  37. * the caller does not need to write something like `it->second.second.second'.
  38. * Instead, the return type is a tuple of references, so that the caller can
  39. * write code like `std::get<3>(*it)'.
  40. *
  41. * For example, the ref type for std::map<int, std::map<float, double> >
  42. * with this would be std::tuple<int const&, float const&, double &>.
  43. */
  44. template <typename Iterator>
  45. 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> {
  46. private:
  47. using super = end_aware_iterator<Iterator>;
  48. using first_type = decltype((std::declval<Iterator>()->first));
  49. using second_type = decltype((std::declval<Iterator>()->second));
  50. protected:
  51. using recursive_category = continue_layer_tag_t;
  52. public:
  53. using value_type = std::tuple<first_type, second_type>;
  54. using reference = std::tuple<first_type &, second_type &>;
  55. public:
  56. using super::super;
  57. recursive_iterator_base() = default;
  58. operator super() const { return *this; }
  59. protected:
  60. /**
  61. * An alternative function to operator*(), which allows single layer
  62. * recursive iterators (on associative containers) to return the
  63. * underlying value/reference type, and nested containers to propogate
  64. * a tuple or a pair as necessary.
  65. */
  66. reference get() {
  67. auto & pair = super::operator*();
  68. return std::tie(pair.first, pair.second);
  69. }
  70. };
  71. /**
  72. * @class recursive_iterator_layer
  73. * @breif A single layer for recursing down a nested collection. Represents non-associative containers.
  74. *
  75. * Provides dispatch/overloading for types and functions of recursive_iterator
  76. * chains to resolve ambiguous typedefs and operators.
  77. *
  78. * @see recursive_iterator_impl
  79. * @see bounded_recursive_iterator_impl
  80. * @param Iterator The underlying iterator type of the layer
  81. * @param RecursiveIterator_NextLayer The next layer, either a recursive_iterator_impl, or a bounded_recursive_iterator_impl
  82. */
  83. template <typename Iterator, typename RecursiveIterator_NextLayer>
  84. class recursive_iterator_layer :
  85. public recursive_iterator_base< Iterator >,
  86. public RecursiveIterator_NextLayer {
  87. private:
  88. using next_layer = RecursiveIterator_NextLayer;
  89. using layer = recursive_iterator_base< Iterator >;
  90. protected:
  91. using recursive_category = continue_layer_tag_t;
  92. public:
  93. using value_type = typename next_layer::value_type;
  94. using reference = typename next_layer::reference;
  95. using pointer = typename next_layer::pointer;
  96. using difference_type = typename next_layer::difference_type;
  97. using iterator_category = typename next_layer::iterator_category;
  98. public:
  99. recursive_iterator_layer() = default;
  100. recursive_iterator_layer(layer v) : recursive_iterator_layer() {
  101. assign(v);
  102. update();
  103. }
  104. template <typename OIter, typename Rec>
  105. recursive_iterator_layer(recursive_iterator_layer<OIter, Rec> const & other) : layer(static_cast<recursive_iterator_base<OIter>const&>(other)), next_layer(static_cast<Rec const&>(other)) {}
  106. template <typename OIter, typename... Iterators>
  107. recursive_iterator_layer(in_place_t, OIter it, Iterators && ...iter)
  108. : layer(it), next_layer(in_place, iter...) {
  109. update();
  110. }
  111. reference operator*() {
  112. return next_layer::get();
  113. }
  114. pointer operator->() {
  115. return next_layer::operator->();
  116. }
  117. bool operator==(recursive_iterator_layer const & other) const {
  118. return layer::operator==(other) && next_layer::operator==(other);
  119. }
  120. protected:
  121. reference get() { return operator*(); }
  122. /**
  123. * Advance the iterator step. If the next layer has reached the end, then
  124. * we advance this iterator until it reaches either its own end, or a
  125. * non-empty subcollection to start iterating over.
  126. */
  127. void next() {
  128. next_layer::next();
  129. update();
  130. }
  131. /**
  132. * Update the underlying iterator and propogate updates down the chain so
  133. * that if there is data available, the iterator is in a dereferencable
  134. * state.
  135. */
  136. void assign(layer v) {
  137. static_cast<layer&>(*this) = v;
  138. if (!v.done()) {
  139. next_layer::assign(make_end_aware_iterator(*v));
  140. }
  141. }
  142. void update() {
  143. layer & self = static_cast<layer&>(*this);
  144. while ( next_layer::done() && !(++self).done() ) {
  145. next_layer::assign(make_end_aware_iterator(*self));
  146. }
  147. }
  148. bool done() const { return layer::done(); }
  149. };
  150. /**
  151. * @class next_layer_type
  152. * @breif A template metaprogramming type for unifying associative and non-associative containers.
  153. */
  154. template <typename V, typename Tag>
  155. struct next_layer_type { using type = std::tuple<V>; };
  156. template <typename V>
  157. struct next_layer_type<V, continue_layer_tag_t> { using type = V; };
  158. /**
  159. * @class flatten_iterator_layer
  160. * @breif A single layer for recursing down a nested collection. Represents associative containers.
  161. *
  162. * @copydoc recursive_iterator_layer
  163. */
  164. template <typename Iterator, typename RecursiveIterator_NextLayer>
  165. class flatten_iterator_layer :
  166. recursive_iterator_base< Iterator >,
  167. RecursiveIterator_NextLayer {
  168. private:
  169. using next_layer = RecursiveIterator_NextLayer;
  170. using layer = recursive_iterator_base< Iterator >;
  171. using key_type = typename std::tuple_element<0, typename layer::value_type>::type;
  172. protected:
  173. using recursive_category = continue_layer_tag_t;
  174. using next_value_type = typename next_layer_type<typename next_layer::value_type, typename next_layer::recursive_category>::type;
  175. using next_reference = typename next_layer_type<typename next_layer::reference, typename next_layer::recursive_category>::type;
  176. public:
  177. using value_type = decltype(std::tuple_cat(std::make_tuple(std::declval<key_type>()),
  178. std::declval<next_value_type>()));
  179. using reference = decltype(std::tuple_cat(std::tie(std::declval<key_type>()),
  180. std::declval<next_reference>()));
  181. using pointer = void;
  182. using difference_type = typename next_layer::difference_type;
  183. using iterator_category = typename next_layer::iterator_category;
  184. public:
  185. flatten_iterator_layer() = default;
  186. flatten_iterator_layer(layer v) : flatten_iterator_layer() {
  187. assign(v);
  188. update();
  189. }
  190. template <typename OIter, typename Rec>
  191. flatten_iterator_layer(flatten_iterator_layer<OIter, Rec> const & other) : layer(static_cast<recursive_iterator_base<OIter>const&>(other)), next_layer(static_cast<Rec const&>(other)) {}
  192. template <typename OIter, typename... Iterators>
  193. flatten_iterator_layer(in_place_t, OIter it, Iterators && ...iter)
  194. : layer(it), next_layer(in_place, iter...) {
  195. update();
  196. }
  197. /**
  198. * @breif Concatenate the key in this layer, with the dereferenced data from the next.
  199. *
  200. * Due to the use of the next_layer_type metaprogramming, a type such as
  201. * std::map<K, std::vector<std::tuple<T1, T2, T3>>> would return a reference
  202. * of type std::tuple<K const &, std::tuple<T1, T2, T3>&>, preserving
  203. * sub-aggregates of pair/tuple type. Similarly, forward_as_tuple means
  204. * even a key-type of pair/tuple will not be unwrapped.
  205. */
  206. reference operator*() {
  207. return std::tuple_cat(std::forward_as_tuple(std::get<0>(layer::get())),
  208. next_reference(next_layer::get()));
  209. }
  210. /**
  211. * Unimplemented because we return an inline constructed type, and tuple
  212. * can only be accessed through std::get anyway.
  213. */
  214. pointer operator->();
  215. bool operator==(flatten_iterator_layer const & other) const {
  216. return layer::operator==(other) && next_layer::operator==(other);
  217. }
  218. protected:
  219. reference get() { return operator*(); }
  220. /**
  221. * @copydoc recursive_iterator_layer::next
  222. */
  223. void next() {
  224. next_layer::next();
  225. update();
  226. }
  227. void update() {
  228. layer & self = static_cast<layer&>(*this);
  229. while ( next_layer::done() && !(++self).done() ) {
  230. next_layer::assign(make_end_aware_iterator(self->second));
  231. }
  232. }
  233. /**
  234. * @copydoc recursive_iterator_layer::assign
  235. */
  236. void assign(layer v) {
  237. static_cast<layer&>(*this) = v;
  238. if ( !v.done() ) {
  239. next_layer::assign(make_end_aware_iterator(v->second));
  240. }
  241. }
  242. bool done() const { return layer::done(); }
  243. };
  244. /**
  245. * @class bounded_recursive_iterator_impl
  246. * @brief The default (terminal) implementation of a recursive iterator up to Max levels deep.
  247. *
  248. * @see recursive_iterator_base
  249. * @param Iterator The iterator type being processed, such as std::vector<int>::iterator
  250. * @param N The current layer of depth, starts at 1.
  251. * @param Max The maximum recursive depth to dive down, in case you need to process some sub-collection in a specific manner.
  252. */
  253. template <typename Iterator, std::size_t N, std::size_t Max, typename = void>
  254. class bounded_recursive_iterator_impl :
  255. public recursive_iterator_base< Iterator > {
  256. private:
  257. using super = recursive_iterator_base< Iterator >;
  258. public:
  259. using super::super;
  260. bounded_recursive_iterator_impl() = default;
  261. template <typename OIter>
  262. bounded_recursive_iterator_impl(in_place_t, OIter iter) : super(iter) {}
  263. protected:
  264. void next() { super::operator++(); }
  265. void assign(super eat) { static_cast<super&>(*this) = eat; }
  266. };
  267. /**
  268. * @class bounded_recursive_iterator_impl
  269. *
  270. * An SFINAE specialization of bounded_recursive_iterator_impl for
  271. * non-associative container types.
  272. * @see recursive_iterator_layer
  273. */
  274. template <typename Iterator, std::size_t N, std::size_t Max>
  275. class bounded_recursive_iterator_impl< Iterator, N, Max, typename std::enable_if<N < Max, typename void_t<value_iterator<Iterator>>::type>::type > :
  276. public recursive_iterator_layer< Iterator , bounded_recursive_iterator_impl< value_iterator<Iterator>, N+1, Max > > {
  277. private:
  278. using next_layer = bounded_recursive_iterator_impl< value_iterator<Iterator>, N+1, Max >;
  279. using super = recursive_iterator_layer< Iterator, next_layer >;
  280. public:
  281. /**
  282. * A special override of operator* that allows collections like
  283. * std::vector<std::vector<std::map<K, V>>> still use the value/reference
  284. * type of the map. Works only for nested collections with one associative
  285. * container at the bottom/Max level.
  286. */
  287. auto operator*() -> decltype(*(next_layer&)(*this)) { return next_layer::operator*(); }
  288. using super::super;
  289. bounded_recursive_iterator_impl() = default;
  290. template <typename... Iterators>
  291. bounded_recursive_iterator_impl(in_place_t, Iterators && ...iter) : super(in_place, iter...) {}
  292. };
  293. /**
  294. * @class recursive_iterator_impl
  295. * @brief The default (terminal) implementation of an unbounded recursive iterator.
  296. *
  297. * @see recursive_iterator_base
  298. * @param Iterator The iterator type being processed, such as std::vector<int>::iterator
  299. */
  300. template <typename Iterator, typename = void>
  301. class recursive_iterator_impl : public recursive_iterator_base< Iterator > {
  302. private:
  303. using super = recursive_iterator_base< Iterator >;
  304. public:
  305. using super::super;
  306. recursive_iterator_impl() = default;
  307. template <typename OIter>
  308. recursive_iterator_impl(in_place_t, OIter iter) : super(iter) {}
  309. protected:
  310. void next() { super::operator++(); }
  311. void assign(super eat) { static_cast<super&>(*this) = eat; }
  312. };
  313. /**
  314. * @class recursive_iterator_impl
  315. *
  316. * An SFINAE specialization of bounded_recursive_iterator_impl for
  317. * non-associative container types.
  318. * @see recursive_iterator_layer
  319. */
  320. template <typename Iterator>
  321. class recursive_iterator_impl< Iterator, typename void_t<value_iterator<Iterator>>::type > :
  322. public recursive_iterator_layer< Iterator, recursive_iterator_impl< value_iterator<Iterator> > > {
  323. private:
  324. using next_layer = recursive_iterator_impl< value_iterator<Iterator> >;
  325. using super = recursive_iterator_layer< Iterator, next_layer >;
  326. public:
  327. /**
  328. * A special override of operator* that allows collections like
  329. * std::vector<std::vector<std::map<K, V>>> still use the value/reference
  330. * type of the map. Works only for nested collections with one associative
  331. * container at the bottom level.
  332. */
  333. auto operator*() -> decltype(*(next_layer&)(*this)) { return next_layer::operator*(); }
  334. using super::super;
  335. recursive_iterator_impl() = default;
  336. template <typename... Iterators>
  337. recursive_iterator_impl(in_place_t, Iterators && ...iter) : super(in_place, iter...) {}
  338. };
  339. /**
  340. * @class bounded_recursive_iterator_impl
  341. *
  342. * An SFINAE specialization of bounded_recursive_iterator_impl for
  343. * associative container types.
  344. * @see flatten_iterator_layer
  345. */
  346. template <typename Iterator, std::size_t N, std::size_t Max>
  347. class bounded_recursive_iterator_impl< Iterator, N, Max, typename std::enable_if<N < Max, typename void_t<mapped_iterator<Iterator>>::type>::type > :
  348. public flatten_iterator_layer< Iterator , bounded_recursive_iterator_impl< mapped_iterator<Iterator>, N+1, Max > > {
  349. private:
  350. using next_layer = bounded_recursive_iterator_impl< mapped_iterator<Iterator>, N+1, Max >;
  351. using super = flatten_iterator_layer< Iterator, next_layer >;
  352. public:
  353. using super::super;
  354. bounded_recursive_iterator_impl() = default;
  355. template <typename... Iterators>
  356. bounded_recursive_iterator_impl(in_place_t, Iterators && ...iter) : super(in_place, iter...) {}
  357. };
  358. /**
  359. * @class recursive_iterator_impl
  360. *
  361. * An SFINAE specialization of bounded_recursive_iterator_impl for
  362. * associative container types.
  363. * @see flatten_iterator_layer
  364. */
  365. template <typename Iterator>
  366. class recursive_iterator_impl< Iterator, typename void_t<mapped_iterator<Iterator>>::type > :
  367. public flatten_iterator_layer< Iterator, recursive_iterator_impl< mapped_iterator<Iterator> > > {
  368. private:
  369. using next_layer = recursive_iterator_impl< mapped_iterator<Iterator> >;
  370. using super = flatten_iterator_layer< Iterator, next_layer >;
  371. public:
  372. using super::super;
  373. recursive_iterator_impl() = default;
  374. template <typename... Iterators>
  375. recursive_iterator_impl(in_place_t, Iterators && ...iter) : super(in_place, iter...) {}
  376. };
  377. }
  378. /**
  379. * @class recursive_iterator
  380. * @breif An iterator type for nested collections, allowing you to treat it as a single-layer collection.
  381. *
  382. * In order to provide a simple interface, if an associative container is used
  383. * in the chain, the type returned by operator*() is a tuple. If multiple
  384. * associative containers are nested, then the tuple will be of the form
  385. * std::tuple<key1, key2, ..., keyN, value>. To avoid copies, and allow
  386. * editting of underlying values, the tuple contains references.
  387. *
  388. * @param Iterator The iterator type of the top-level collection.
  389. */
  390. template <typename Iterator>
  391. class recursive_iterator : public detail::recursive_iterator_impl< Iterator > {
  392. private:
  393. using super = detail::recursive_iterator_impl< Iterator >;
  394. public:
  395. using super::super;
  396. recursive_iterator() = default;
  397. template <typename... Iterators>
  398. recursive_iterator(in_place_t, Iterators && ...iter) : super(in_place, iter...) {}
  399. recursive_iterator & operator++() {
  400. (void) super::next();
  401. return *this;
  402. }
  403. recursive_iterator operator++(int) {
  404. recursive_iterator tmp{*this};
  405. (void) super::next();
  406. return tmp;
  407. }
  408. bool operator!=(recursive_iterator const & other) { return !(super::operator==(other)); }
  409. };
  410. /**
  411. * @class recursive_iterator_n
  412. * @copydoc recursive_iterator
  413. * This object has bounded recursive depth, so that it can be used to get
  414. * sub-collections, which may be used in other functions.
  415. *
  416. * For Example:
  417. * @code
  418. * using map_type = std::map<std::string, std::map<std::string, std::vector<Data> > >;
  419. * ...
  420. * recursive_iterator_n<map_type::iterator, 2> iter{ ... };
  421. * std::vector<Data> & data = std::get<2>(*iter);
  422. * reload_data_from_file( std::get<1>(*iter), data );
  423. * @endcode
  424. *
  425. * @param N The maximum depth to recurse into the object
  426. */
  427. template <typename Iterator, std::size_t N>
  428. class recursive_iterator_n : public detail::bounded_recursive_iterator_impl< Iterator, 1, N > {
  429. private:
  430. using super = detail::bounded_recursive_iterator_impl< Iterator, 1, N >;
  431. public:
  432. using super::super;
  433. recursive_iterator_n() = default;
  434. template <typename... Iterators>
  435. recursive_iterator_n(in_place_t, Iterators && ...iter) : super(in_place, iter...) {}
  436. recursive_iterator_n & operator++() {
  437. (void) super::next();
  438. return *this;
  439. }
  440. recursive_iterator_n operator++(int) {
  441. recursive_iterator_n tmp{*this};
  442. (void) super::next();
  443. return tmp;
  444. }
  445. bool operator!=(recursive_iterator_n const & other) { return !(super::operator==(other)); }
  446. };
  447. }
  448. template <typename C>
  449. auto make_recursive_iterator(C & collect) -> iterator::recursive_iterator<decltype(std::begin(collect))> {
  450. return { make_end_aware_iterator(collect)};
  451. }
  452. template <typename C>
  453. auto make_recursive_iterator(C const & collect) -> iterator::recursive_iterator<decltype(std::begin(collect))> {
  454. return { make_end_aware_iterator(collect) };
  455. }
  456. template <std::size_t Max, typename C>
  457. auto make_recursive_iterator(C & collect) -> iterator::recursive_iterator_n<decltype(std::begin(collect)), Max> {
  458. return { make_end_aware_iterator(collect) };
  459. }
  460. template <std::size_t Max, typename C>
  461. auto make_recursive_iterator(C const & collect) -> iterator::recursive_iterator_n<decltype(std::begin(collect)), Max> {
  462. return { make_end_aware_iterator(collect) };
  463. }