flatten_iterator.hpp 6.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207
  1. //
  2. // flatten_iterator.hpp
  3. // iterator
  4. //
  5. // Created by Sam Jaffe on 2/17/17.
  6. //
  7. #pragma once
  8. #include "iterator_fwd.hpp"
  9. #include <tuple>
  10. namespace iterator {
  11. namespace detail {
  12. template <typename Iterator>
  13. using flatten_iterator_base = end_aware_iterator< Iterator >;
  14. template <typename Iterator>
  15. class flatten_iterator_terminal : flatten_iterator_base< Iterator > {
  16. private:
  17. using layer = flatten_iterator_base< Iterator >;
  18. using first_type = typename layer::value_type::first_type;
  19. using second_type = typename layer::value_type::second_type;
  20. public:
  21. using value_type = std::tuple<first_type, second_type>;
  22. using reference = std::tuple<first_type &, second_type &>;
  23. // using pointer = typename layer::pointer;
  24. using difference_type = typename layer::difference_type;
  25. using iterator_category = typename layer::iterator_category;
  26. public:
  27. flatten_iterator_terminal() = default;
  28. flatten_iterator_terminal(layer v) : layer(v) {}
  29. reference operator*() {
  30. return layer::operator*();
  31. }
  32. // pointer operator->() {
  33. // return layer::operator->();
  34. // }
  35. bool operator==(flatten_iterator_terminal const & other) const {
  36. return layer::operator==(other);
  37. }
  38. protected:
  39. void next() {
  40. layer::operator++();
  41. }
  42. void assign(layer eat) {
  43. static_cast<layer&>(*this) = eat;
  44. }
  45. bool done() const { return layer::done(); }
  46. };
  47. template <typename Iterator, typename RecursiveIterator_NextLayer>
  48. class flatten_iterator_layer :
  49. flatten_iterator_base< Iterator >,
  50. RecursiveIterator_NextLayer {
  51. private:
  52. using next_layer = RecursiveIterator_NextLayer;
  53. using layer = flatten_iterator_base< Iterator >;
  54. using key_type = typename layer::value_type::first_type;
  55. using cat_value_type = typename next_layer::value_type;
  56. using cat_reference = typename next_layer::reference;
  57. public:
  58. using value_type = decltype(std::tuple_cat(std::make_tuple(std::declval<key_type>()), std::declval<cat_value_type>()));
  59. using reference = decltype(std::tuple_cat(std::tie(std::declval<key_type>()), std::declval<cat_reference>()));
  60. // using pointer = typename next_layer::pointer;
  61. using difference_type = typename next_layer::difference_type;
  62. using iterator_category = typename next_layer::iterator_category;
  63. public:
  64. flatten_iterator_layer() = default;
  65. flatten_iterator_layer(layer v) : layer(v), next_layer() {
  66. if ( !v.done() ) {
  67. next_layer::assign({ std::begin(v->second), std::end(v->second) });
  68. }
  69. }
  70. reference operator*() {
  71. return std::tuple_cat(std::tie(layer::operator*().first), next_layer::operator*());
  72. }
  73. // pointer operator->() {
  74. // return next_layer::operator->();
  75. // }
  76. bool operator==(flatten_iterator_layer const & other) const {
  77. return layer::operator==(other) && next_layer::operator==(other);
  78. }
  79. protected:
  80. void next() {
  81. layer & self = static_cast<layer&>(*this);
  82. next_layer::next();
  83. while ( next_layer::done() && !(++self).done() ) {
  84. next_layer::assign({ std::begin(self->second), std::end(self->second) });
  85. }
  86. }
  87. void assign(layer eat) {
  88. static_cast<layer&>(*this) = eat;
  89. }
  90. bool done() const { return layer::done(); }
  91. };
  92. template <typename Iterator, std::size_t N, std::size_t Max, typename = void>
  93. class bounded_flatten_iterator_impl :
  94. public flatten_iterator_terminal< Iterator > {
  95. private:
  96. using super = flatten_iterator_terminal< Iterator >;
  97. public:
  98. using super::super;
  99. };
  100. template <typename Iterator, std::size_t N, std::size_t Max>
  101. class bounded_flatten_iterator_impl< Iterator, N, Max, typename std::enable_if<N < Max, typename void_t<mapped_iterator<Iterator>>::type>::type > :
  102. public flatten_iterator_layer< Iterator , bounded_flatten_iterator_impl< mapped_iterator<Iterator>, N+1, Max > > {
  103. private:
  104. using next_layer = bounded_flatten_iterator_impl< mapped_iterator<Iterator>, N+1, Max >;
  105. using super = flatten_iterator_layer< Iterator, next_layer >;
  106. public:
  107. using super::super;
  108. };
  109. template <typename Iterator, typename = void>
  110. class flatten_iterator_impl : public flatten_iterator_terminal< Iterator > {
  111. private:
  112. using super = flatten_iterator_terminal< Iterator >;
  113. public:
  114. using super::super;
  115. };
  116. template <typename Iterator>
  117. class flatten_iterator_impl< Iterator, typename void_t<mapped_iterator<Iterator>>::type > :
  118. public flatten_iterator_layer< Iterator, flatten_iterator_impl< mapped_iterator<Iterator> > > {
  119. private:
  120. using next_layer = flatten_iterator_impl< mapped_iterator<Iterator> >;
  121. using super = flatten_iterator_layer< Iterator, next_layer >;
  122. public:
  123. using super::super;
  124. };
  125. }
  126. template <typename Iterator>
  127. class flatten_iterator : detail::flatten_iterator_impl< Iterator > {
  128. private:
  129. using super = detail::flatten_iterator_impl< Iterator >;
  130. public:
  131. using value_type = typename super::value_type;
  132. using reference = typename super::reference;
  133. // using pointer = typename super::pointer;
  134. using difference_type = typename super::difference_type;
  135. using iterator_category = typename super::iterator_category;
  136. public:
  137. using super::super;
  138. flatten_iterator & operator++() {
  139. (void) super::next();
  140. return *this;
  141. }
  142. flatten_iterator operator++(int) {
  143. flatten_iterator tmp{*this};
  144. (void) super::next();
  145. return tmp;
  146. }
  147. using super::operator*;
  148. // using super::operator->;
  149. using super::operator==;
  150. bool operator!=(flatten_iterator const & other) { return !(operator==(other)); }
  151. };
  152. template <typename Iterator, std::size_t N>
  153. class flatten_iterator_n : detail::bounded_flatten_iterator_impl< Iterator, 1, N > {
  154. private:
  155. using super = detail::bounded_flatten_iterator_impl< Iterator, 1, N >;
  156. public:
  157. using value_type = typename super::value_type;
  158. using reference = typename super::reference;
  159. // using pointer = typename super::pointer;
  160. using difference_type = typename super::difference_type;
  161. using iterator_category = typename super::iterator_category;
  162. public:
  163. using super::super;
  164. flatten_iterator_n & operator++() {
  165. (void) super::next();
  166. return *this;
  167. }
  168. flatten_iterator_n operator++(int) {
  169. flatten_iterator_n tmp{*this};
  170. (void) super::next();
  171. return tmp;
  172. }
  173. using super::operator*;
  174. // using super::operator->;
  175. using super::operator==;
  176. bool operator!=(flatten_iterator_n const & other) { return !(operator==(other)); }
  177. };
  178. }