flatten_layer.hpp 2.7 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091
  1. #pragma once
  2. #include "../detail/arrow_proxy.h"
  3. #include "base.hpp"
  4. #include "traits.hpp"
  5. namespace iterator::recursive {
  6. /**
  7. * @class flatten_iterator_layer
  8. * @brief A single layer for recursing down a nested collection. Represents
  9. * associative containers.
  10. *
  11. * @copydoc recursive_iterator_layer
  12. */
  13. template <typename Iterator, typename Next>
  14. class flatten_layer : public base<Iterator>, public Next {
  15. protected:
  16. using recursive_category = continue_layer_tag_t;
  17. public:
  18. flatten_layer() = default;
  19. explicit flatten_layer(base<Iterator> v) : flatten_layer() {
  20. assign(v);
  21. update();
  22. }
  23. template <typename OIter, typename Rec>
  24. flatten_layer(flatten_layer<OIter, Rec> const & other)
  25. : base<Iterator>(static_cast<base<OIter> const &>(other)),
  26. Next(static_cast<Rec const &>(other)) {}
  27. /**
  28. * @brief Concatenate the key in this layer, with the dereferenced data from
  29. * the next.
  30. *
  31. * Due to the use of the next_layer_type metaprogramming, a type such as
  32. * std::map<K, std::vector<std::tuple<T1, T2, T3>>> would return a reference
  33. * of type std::tuple<K const &, std::tuple<T1, T2, T3>&>, preserving
  34. * sub-aggregates of pair/tuple type. Similarly, forward_as_tuple means
  35. * even a key-type of pair/tuple will not be unwrapped.
  36. */
  37. decltype(auto) operator*() const {
  38. using next_t =
  39. typename next_layer_type<decltype(Next::get()),
  40. typename Next::recursive_category>::type;
  41. return std::tuple_cat(
  42. std::forward_as_tuple(std::get<0>(base<Iterator>::get())),
  43. next_t(Next::get()));
  44. }
  45. /**
  46. * Unimplemented because we return an inline constructed type, and tuple
  47. * can only be accessed through std::get anyway.
  48. */
  49. // auto operator->() const { return detail::arrow_proxy(**this); }
  50. void operator->() const;
  51. bool operator==(flatten_layer const & other) const {
  52. return (static_cast<base<Iterator> const &>(*this) == other) &&
  53. (static_cast<Next const &>(*this) == other);
  54. }
  55. protected:
  56. decltype(auto) get() const { return **this; }
  57. /**
  58. * @copydoc recursive_iterator_layer::next
  59. */
  60. void next() {
  61. Next::next();
  62. update();
  63. }
  64. void update() {
  65. base<Iterator> & self = static_cast<base<Iterator> &>(*this);
  66. while (Next::at_end() && !(++self).at_end()) {
  67. Next::assign(make_end_aware_iterator(self->second));
  68. }
  69. }
  70. /**
  71. * @copydoc recursive_iterator_layer::assign
  72. */
  73. void assign(base<Iterator> v) {
  74. static_cast<base<Iterator> &>(*this) = v;
  75. if (!v.at_end()) { Next::assign(make_end_aware_iterator(v->second)); }
  76. }
  77. using base<Iterator>::at_end;
  78. };
  79. }