recursive_iterator.hpp 14 KB

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