recursive_iterator.hpp 4.9 KB

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