recursive_iterator.hpp 4.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148
  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 "detail/recursive_iterator_impl.hpp"
  12. #include "detail/recursive_iterator_traits.hpp"
  13. #include "iterator_fwd.hpp"
  14. namespace iterator {
  15. /**
  16. * @class recursive_iterator
  17. * @brief An iterator type for nested collections, allowing you to treat it as
  18. * a single-layer collection.
  19. *
  20. * In order to provide a simple interface, if an associative container is used
  21. * in the chain, the type returned by operator*() is a tuple. If multiple
  22. * associative containers are nested, then the tuple will be of the form
  23. * std::tuple<key1, key2, ..., keyN, value>. To avoid copies, and allow
  24. * editting of underlying values, the tuple contains references.
  25. *
  26. * @tparam Iterator The iterator type of the top-level collection.
  27. */
  28. template <typename Iterator>
  29. class recursive_iterator : public detail::recursive_iterator_impl<Iterator> {
  30. public:
  31. using super = detail::recursive_iterator_impl<Iterator>;
  32. public:
  33. using super::super;
  34. recursive_iterator() = default;
  35. recursive_iterator & operator++() {
  36. (void)super::next();
  37. return *this;
  38. }
  39. recursive_iterator operator++(int) {
  40. recursive_iterator tmp{*this};
  41. (void)super::next();
  42. return tmp;
  43. }
  44. bool operator!=(recursive_iterator const & other) const {
  45. return !(super::operator==(other));
  46. }
  47. };
  48. /**
  49. * @class recursive_iterator_n
  50. * @copydoc recursive_iterator
  51. * This object has bounded recursive depth, so that it can be used to get
  52. * sub-collections, which may be used in other functions.
  53. *
  54. * For Example:
  55. * @code
  56. * using map_type = std::map<std::string, std::map<std::string,
  57. * std::vector<Data> > >;
  58. * ...
  59. * recursive_iterator_n<map_type::iterator, 2> iter{ ... };
  60. * std::vector<Data> & data = std::get<2>(*iter);
  61. * reload_data_from_file( std::get<1>(*iter), data );
  62. * @endcode
  63. *
  64. * @tparam N The maximum depth to recurse into the object
  65. */
  66. template <typename Iterator, std::size_t N>
  67. class recursive_iterator_n
  68. : public detail::bounded_recursive_iterator_impl<Iterator, 1, N> {
  69. public:
  70. using super = detail::bounded_recursive_iterator_impl<Iterator, 1, N>;
  71. public:
  72. using super::super;
  73. recursive_iterator_n() = default;
  74. recursive_iterator_n & operator++() {
  75. (void)super::next();
  76. return *this;
  77. }
  78. recursive_iterator_n operator++(int) {
  79. recursive_iterator_n tmp{*this};
  80. (void)super::next();
  81. return tmp;
  82. }
  83. bool operator!=(recursive_iterator_n const & other) const {
  84. return !(super::operator==(other));
  85. }
  86. };
  87. }
  88. namespace std {
  89. template <std::size_t I, typename It>
  90. auto get(::iterator::recursive_iterator<It> const & iter) ->
  91. typename ::iterator::detail::accessor<
  92. I, ::iterator::recursive_iterator<It>>::type {
  93. return iter;
  94. }
  95. template <std::size_t I, typename It, std::size_t N>
  96. auto get(::iterator::recursive_iterator_n<It, N> const & iter) ->
  97. typename ::iterator::detail::accessor<
  98. I, ::iterator::recursive_iterator_n<It, N>>::type {
  99. static_assert(I < N, "Cannot get past bounding level");
  100. return iter;
  101. }
  102. }
  103. // template <typename Iter0, typename... Iters>
  104. // auto make_recursive_iterator(iterator::end_aware_iterator<Iter0> it,
  105. // Iters &&... iters)
  106. // -> iterator::recursive_iterator<Iter0> {
  107. // return {iterator::in_place, std::move(it), std::forward<Iters>(iters)...};
  108. //}
  109. template <typename C>
  110. auto make_recursive_iterator(C & collect)
  111. -> iterator::recursive_iterator<decltype(std::begin(collect))> {
  112. return {make_end_aware_iterator(collect)};
  113. }
  114. template <typename C>
  115. auto make_recursive_iterator(C const & collect)
  116. -> iterator::recursive_iterator<decltype(std::begin(collect))> {
  117. return {make_end_aware_iterator(collect)};
  118. }
  119. template <std::size_t Max, typename C>
  120. auto make_recursive_iterator(C & collect)
  121. -> iterator::recursive_iterator_n<decltype(std::begin(collect)), Max> {
  122. return {make_end_aware_iterator(collect)};
  123. }
  124. template <std::size_t Max, typename C>
  125. auto make_recursive_iterator(C const & collect)
  126. -> iterator::recursive_iterator_n<decltype(std::begin(collect)), Max> {
  127. return {make_end_aware_iterator(collect)};
  128. }