recursive_iterator.hpp 14 KB

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