recursive_iterator.hpp 4.0 KB

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