recursive_iterator.hpp 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444
  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 &&... iter)
  129. : layer(std::forward<OIter>(it)),
  130. super(in_place, std::forward<Iterators>(iter)...) {
  131. update();
  132. }
  133. reference operator*() const { return super::get(); }
  134. pointer operator->() const { return super::operator->(); }
  135. bool operator==(recursive_iterator_layer const & other) const {
  136. return layer::operator==(other) && super::operator==(other);
  137. }
  138. protected:
  139. reference get() const { return operator*(); }
  140. /**
  141. * Advance the iterator step. If the next layer has reached the end, then
  142. * we advance this iterator until it reaches either its own end, or a
  143. * non-empty subcollection to start iterating over.
  144. */
  145. void next() {
  146. super::next();
  147. update();
  148. }
  149. /**
  150. * Update the underlying iterator and propogate updates down the chain so
  151. * that if there is data available, the iterator is in a dereferencable
  152. * state.
  153. */
  154. void assign(layer v) {
  155. static_cast<layer &>(*this) = v;
  156. if (!v.done()) { super::assign(make_end_aware_iterator(*v)); }
  157. }
  158. void update() {
  159. layer & self = static_cast<layer &>(*this);
  160. while (super::done() && !(++self).done()) {
  161. super::assign(make_end_aware_iterator(*self));
  162. }
  163. }
  164. bool done() const { return layer::done(); }
  165. };
  166. /**
  167. * @class next_layer_type
  168. * @breif A template metaprogramming type for unifying associative and
  169. * non-associative containers.
  170. */
  171. template <typename V, typename Tag> struct next_layer_type {
  172. using type = std::tuple<V>;
  173. };
  174. template <typename V> struct next_layer_type<V, continue_layer_tag_t> {
  175. using type = V;
  176. };
  177. /**
  178. * @class flatten_iterator_layer
  179. * @brief A single layer for recursing down a nested collection. Represents
  180. * associative containers.
  181. *
  182. * @copydoc recursive_iterator_layer
  183. */
  184. template <typename Iterator, typename RecursiveIterator_NextLayer>
  185. class flatten_iterator_layer : public recursive_iterator_base<Iterator>,
  186. public RecursiveIterator_NextLayer {
  187. public:
  188. using super = RecursiveIterator_NextLayer;
  189. using layer = recursive_iterator_base<Iterator>;
  190. using key_type =
  191. typename std::tuple_element<0, typename layer::value_type>::type;
  192. protected:
  193. using recursive_category = continue_layer_tag_t;
  194. using next_value_type =
  195. typename next_layer_type<typename super::value_type,
  196. typename super::recursive_category>::type;
  197. using next_reference =
  198. typename next_layer_type<typename super::reference,
  199. typename super::recursive_category>::type;
  200. public:
  201. using value_type =
  202. decltype(std::tuple_cat(std::make_tuple(std::declval<key_type>()),
  203. std::declval<next_value_type>()));
  204. using reference = decltype(std::tuple_cat(
  205. std::tie(std::declval<key_type>()), std::declval<next_reference>()));
  206. using pointer = void;
  207. using difference_type = typename super::difference_type;
  208. using iterator_category = std::forward_iterator_tag;
  209. public:
  210. flatten_iterator_layer() = default;
  211. flatten_iterator_layer(layer v) : flatten_iterator_layer() {
  212. assign(v);
  213. update();
  214. }
  215. template <typename OIter, typename Rec>
  216. flatten_iterator_layer(flatten_iterator_layer<OIter, Rec> const & other)
  217. : layer(static_cast<recursive_iterator_base<OIter> const &>(other)),
  218. super(static_cast<Rec const &>(other)) {}
  219. template <typename OIter, typename... Iterators>
  220. flatten_iterator_layer(in_place_t, OIter && it, Iterators &&... iter)
  221. : layer(std::forward<OIter>(it)),
  222. super(in_place, std::forward<Iterators>(iter)...) {
  223. update();
  224. }
  225. /**
  226. * @brief Concatenate the key in this layer, with the dereferenced data from
  227. * the next.
  228. *
  229. * Due to the use of the next_layer_type metaprogramming, a type such as
  230. * std::map<K, std::vector<std::tuple<T1, T2, T3>>> would return a reference
  231. * of type std::tuple<K const &, std::tuple<T1, T2, T3>&>, preserving
  232. * sub-aggregates of pair/tuple type. Similarly, forward_as_tuple means
  233. * even a key-type of pair/tuple will not be unwrapped.
  234. */
  235. reference operator*() const {
  236. return std::tuple_cat(std::forward_as_tuple(std::get<0>(layer::get())),
  237. next_reference(super::get()));
  238. }
  239. /**
  240. * Unimplemented because we return an inline constructed type, and tuple
  241. * can only be accessed through std::get anyway.
  242. */
  243. pointer operator->() const;
  244. bool operator==(flatten_iterator_layer const & other) const {
  245. return layer::operator==(other) && super::operator==(other);
  246. }
  247. protected:
  248. reference get() const { return operator*(); }
  249. /**
  250. * @copydoc recursive_iterator_layer::next
  251. */
  252. void next() {
  253. super::next();
  254. update();
  255. }
  256. void update() {
  257. layer & self = static_cast<layer &>(*this);
  258. while (super::done() && !(++self).done()) {
  259. super::assign(make_end_aware_iterator(self->second));
  260. }
  261. }
  262. /**
  263. * @copydoc recursive_iterator_layer::assign
  264. */
  265. void assign(layer v) {
  266. static_cast<layer &>(*this) = v;
  267. if (!v.done()) { super::assign(make_end_aware_iterator(v->second)); }
  268. }
  269. bool done() const { return layer::done(); }
  270. };
  271. }}
  272. #include "recursive_iterator_meta.hpp"
  273. namespace iterator {
  274. /**
  275. * @class recursive_iterator
  276. * @brief An iterator type for nested collections, allowing you to treat it as
  277. * a single-layer collection.
  278. *
  279. * In order to provide a simple interface, if an associative container is used
  280. * in the chain, the type returned by operator*() is a tuple. If multiple
  281. * associative containers are nested, then the tuple will be of the form
  282. * std::tuple<key1, key2, ..., keyN, value>. To avoid copies, and allow
  283. * editting of underlying values, the tuple contains references.
  284. *
  285. * @tparam Iterator The iterator type of the top-level collection.
  286. */
  287. template <typename Iterator>
  288. class recursive_iterator : public detail::recursive_iterator_impl<Iterator> {
  289. public:
  290. using super = detail::recursive_iterator_impl<Iterator>;
  291. public:
  292. using super::super;
  293. recursive_iterator() = default;
  294. template <typename... Iterators>
  295. recursive_iterator(in_place_t, Iterators &&... iter)
  296. : super(in_place, std::forward<Iterators>(iter)...) {}
  297. recursive_iterator & operator++() {
  298. (void)super::next();
  299. return *this;
  300. }
  301. recursive_iterator operator++(int) {
  302. recursive_iterator tmp{*this};
  303. (void)super::next();
  304. return tmp;
  305. }
  306. bool operator!=(recursive_iterator const & other) {
  307. return !(super::operator==(other));
  308. }
  309. };
  310. /**
  311. * @class recursive_iterator_n
  312. * @copydoc recursive_iterator
  313. * This object has bounded recursive depth, so that it can be used to get
  314. * sub-collections, which may be used in other functions.
  315. *
  316. * For Example:
  317. * @code
  318. * using map_type = std::map<std::string, std::map<std::string,
  319. * std::vector<Data> > >;
  320. * ...
  321. * recursive_iterator_n<map_type::iterator, 2> iter{ ... };
  322. * std::vector<Data> & data = std::get<2>(*iter);
  323. * reload_data_from_file( std::get<1>(*iter), data );
  324. * @endcode
  325. *
  326. * @tparam N The maximum depth to recurse into the object
  327. */
  328. template <typename Iterator, std::size_t N>
  329. class recursive_iterator_n
  330. : public detail::bounded_recursive_iterator_impl<Iterator, 1, N> {
  331. public:
  332. using super = detail::bounded_recursive_iterator_impl<Iterator, 1, N>;
  333. public:
  334. using super::super;
  335. recursive_iterator_n() = default;
  336. template <typename... Iterators>
  337. recursive_iterator_n(in_place_t, Iterators &&... iter)
  338. : super(in_place, std::forward<Iterators>(iter)...) {}
  339. recursive_iterator_n & operator++() {
  340. (void)super::next();
  341. return *this;
  342. }
  343. recursive_iterator_n operator++(int) {
  344. recursive_iterator_n tmp{*this};
  345. (void)super::next();
  346. return tmp;
  347. }
  348. bool operator!=(recursive_iterator_n const & other) {
  349. return !(super::operator==(other));
  350. }
  351. };
  352. }
  353. namespace std {
  354. template <std::size_t I, typename It>
  355. auto get(::iterator::recursive_iterator<It> const & iter) ->
  356. typename ::iterator::detail::accessor<
  357. I, ::iterator::recursive_iterator<It>>::type {
  358. return iter;
  359. }
  360. }
  361. template <typename Iter0, typename... Iters>
  362. auto make_recursive_iterator(iterator::end_aware_iterator<Iter0> it,
  363. Iters &&... iters)
  364. -> iterator::recursive_iterator<Iter0> {
  365. return {iterator::in_place, std::move(it), std::forward<Iters>(iters)...};
  366. }
  367. template <typename C>
  368. auto make_recursive_iterator(C & collect)
  369. -> iterator::recursive_iterator<decltype(std::begin(collect))> {
  370. return {make_end_aware_iterator(collect)};
  371. }
  372. template <typename C>
  373. auto make_recursive_iterator(C const & collect)
  374. -> iterator::recursive_iterator<decltype(std::begin(collect))> {
  375. return {make_end_aware_iterator(collect)};
  376. }
  377. template <std::size_t Max, typename C>
  378. auto make_recursive_iterator(C & collect)
  379. -> iterator::recursive_iterator_n<decltype(std::begin(collect)), Max> {
  380. return {make_end_aware_iterator(collect)};
  381. }
  382. template <std::size_t Max, typename C>
  383. auto make_recursive_iterator(C const & collect)
  384. -> iterator::recursive_iterator_n<decltype(std::begin(collect)), Max> {
  385. return {make_end_aware_iterator(collect)};
  386. }