recursive_iterator.hpp 17 KB

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