impl.hpp 4.7 KB

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