recursive_iterator_meta.hpp 7.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190
  1. //
  2. // recursive_iterator_meta.hpp
  3. // iterator
  4. //
  5. // Created by Sam Jaffe on 2/21/17.
  6. //
  7. #pragma once
  8. namespace iterator { namespace detail {
  9. /**
  10. * @class recursive_iterator_impl
  11. * @brief The default (terminal) implementation of an unbounded recursive iterator.
  12. *
  13. * @see recursive_iterator_base
  14. * @param Iterator The iterator type being processed, such as std::vector<int>::iterator
  15. */
  16. template <typename Iterator, typename = void>
  17. class recursive_iterator_impl : public recursive_iterator_base< Iterator > {
  18. public:
  19. using super = recursive_iterator_base< Iterator >;
  20. public:
  21. using super::super;
  22. recursive_iterator_impl() = default;
  23. template <typename OIter>
  24. recursive_iterator_impl(in_place_t, OIter iter) : super(iter) {}
  25. protected:
  26. void next() { super::operator++(); }
  27. void assign(super eat) { static_cast<super&>(*this) = eat; }
  28. };
  29. /**
  30. * @class recursive_iterator_impl
  31. *
  32. * An SFINAE specialization of bounded_recursive_iterator_impl for
  33. * non-associative container types.
  34. * @see recursive_iterator_layer
  35. */
  36. template <typename Iterator>
  37. class recursive_iterator_impl< Iterator, typename void_t<value_iterator<Iterator>>::type > :
  38. public recursive_iterator_layer< Iterator, recursive_iterator_impl< value_iterator<Iterator> > > {
  39. public:
  40. using next_layer = recursive_iterator_impl< value_iterator<Iterator> >;
  41. using super = recursive_iterator_layer< Iterator, next_layer >;
  42. public:
  43. /**
  44. * A special override of operator* that allows collections like
  45. * std::vector<std::vector<std::map<K, V>>> still use the value/reference
  46. * type of the map. Works only for nested collections with one associative
  47. * container at the bottom level.
  48. */
  49. auto operator*() const -> decltype(*(next_layer&)(*this)) { return next_layer::operator*(); }
  50. using super::super;
  51. recursive_iterator_impl() = default;
  52. template <typename... Iterators>
  53. recursive_iterator_impl(in_place_t, Iterators && ...iter) : super(in_place, iter...) {}
  54. };
  55. /**
  56. * @class recursive_iterator_impl
  57. *
  58. * An SFINAE specialization of bounded_recursive_iterator_impl for
  59. * associative container types.
  60. * @see flatten_iterator_layer
  61. */
  62. template <typename Iterator>
  63. class recursive_iterator_impl< Iterator, typename void_t<mapped_iterator<Iterator>>::type > :
  64. public flatten_iterator_layer< Iterator, recursive_iterator_impl< mapped_iterator<Iterator> > > {
  65. public:
  66. using next_layer = recursive_iterator_impl< mapped_iterator<Iterator> >;
  67. using super = flatten_iterator_layer< Iterator, next_layer >;
  68. public:
  69. using super::super;
  70. recursive_iterator_impl() = default;
  71. template <typename... Iterators>
  72. recursive_iterator_impl(in_place_t, Iterators && ...iter) : super(in_place, iter...) {}
  73. };
  74. /**
  75. * @class bounded_recursive_iterator_impl
  76. * @brief The default (terminal) implementation of a recursive iterator up to Max levels deep.
  77. *
  78. * @see recursive_iterator_base
  79. * @param Iterator The iterator type being processed, such as std::vector<int>::iterator
  80. * @param N The current layer of depth, starts at 1.
  81. * @param Max The maximum recursive depth to dive down, in case you need to process some sub-collection in a specific manner.
  82. */
  83. template <typename Iterator, std::size_t N, std::size_t Max, typename = void>
  84. class bounded_recursive_iterator_impl :
  85. public recursive_iterator_base< Iterator > {
  86. public:
  87. using super = recursive_iterator_base< Iterator >;
  88. public:
  89. using super::super;
  90. bounded_recursive_iterator_impl() = default;
  91. template <typename OIter>
  92. bounded_recursive_iterator_impl(in_place_t, OIter iter) : super(iter) {}
  93. protected:
  94. void next() { super::operator++(); }
  95. void assign(super eat) { static_cast<super&>(*this) = eat; }
  96. };
  97. /**
  98. * @class bounded_recursive_iterator_impl
  99. *
  100. * An SFINAE specialization of bounded_recursive_iterator_impl for
  101. * non-associative container types.
  102. * @see recursive_iterator_layer
  103. */
  104. template <typename Iterator, std::size_t N, std::size_t Max>
  105. class bounded_recursive_iterator_impl< Iterator, N, Max, typename std::enable_if<N < Max, typename void_t<value_iterator<Iterator>>::type>::type > :
  106. public recursive_iterator_layer< Iterator , bounded_recursive_iterator_impl< value_iterator<Iterator>, N+1, Max > > {
  107. public:
  108. using next_layer = bounded_recursive_iterator_impl< value_iterator<Iterator>, N+1, Max >;
  109. using super = recursive_iterator_layer< Iterator, next_layer >;
  110. public:
  111. /**
  112. * A special override of operator* that allows collections like
  113. * std::vector<std::vector<std::map<K, V>>> still use the value/reference
  114. * type of the map. Works only for nested collections with one associative
  115. * container at the bottom/Max level.
  116. */
  117. auto operator*() const -> decltype(*(next_layer&)(*this)) { return next_layer::operator*(); }
  118. using super::super;
  119. bounded_recursive_iterator_impl() = default;
  120. template <typename... Iterators>
  121. bounded_recursive_iterator_impl(in_place_t, Iterators && ...iter) : super(in_place, iter...) {}
  122. };
  123. /**
  124. * @class bounded_recursive_iterator_impl
  125. *
  126. * An SFINAE specialization of bounded_recursive_iterator_impl for
  127. * associative container types.
  128. * @see flatten_iterator_layer
  129. */
  130. template <typename Iterator, std::size_t N, std::size_t Max>
  131. class bounded_recursive_iterator_impl< Iterator, N, Max, typename std::enable_if<N < Max, typename void_t<mapped_iterator<Iterator>>::type>::type > :
  132. public flatten_iterator_layer< Iterator , bounded_recursive_iterator_impl< mapped_iterator<Iterator>, N+1, Max > > {
  133. public:
  134. using next_layer = bounded_recursive_iterator_impl< mapped_iterator<Iterator>, N+1, Max >;
  135. using super = flatten_iterator_layer< Iterator, next_layer >;
  136. public:
  137. using super::super;
  138. bounded_recursive_iterator_impl() = default;
  139. template <typename... Iterators>
  140. bounded_recursive_iterator_impl(in_place_t, Iterators && ...iter) : super(in_place, iter...) {}
  141. };
  142. } }
  143. namespace iterator { namespace detail {
  144. template <std::size_t I, typename It, typename = void>
  145. struct accessor;
  146. template <typename It>
  147. struct accessor<0, end_aware_iterator<It>> {
  148. using type = end_aware_iterator<It>;
  149. };
  150. template <typename It, typename Rec>
  151. struct accessor<0, recursive_iterator_layer<It, Rec>> {
  152. using type = end_aware_iterator<It>;
  153. };
  154. template <typename It, typename Rec>
  155. struct accessor<0, flatten_iterator_layer<It, Rec>> {
  156. using type = end_aware_iterator<It>;
  157. };
  158. template <typename It>
  159. struct accessor<0, It> {
  160. using type = typename accessor<0, typename It::super>::type;
  161. };
  162. template <std::size_t I, typename It>
  163. struct accessor<I, It, typename std::enable_if<I != 0>::type> {
  164. using type = typename accessor<I, typename It::super>::type;
  165. };
  166. template <std::size_t I, typename It, typename Rec>
  167. struct accessor<I, recursive_iterator_layer<It, Rec>, typename std::enable_if<I != 0>::type> {
  168. using type = typename accessor<I-1, Rec>::type;
  169. };
  170. template <std::size_t I, typename It, typename Rec>
  171. struct accessor<I, flatten_iterator_layer<It, Rec>, typename std::enable_if<I != 0>::type> {
  172. using type = typename accessor<I-1, Rec>::type;
  173. };
  174. } }