recursive_iterator.hpp 15 KB

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