flatten_iterator_layer.hpp 3.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110
  1. #pragma once
  2. #include "arrow_proxy.h"
  3. #include "recursive_iterator_base.hpp"
  4. #include "recursive_iterator_traits.hpp"
  5. namespace iterator { namespace detail {
  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 RecursiveIterator_NextLayer>
  14. class flatten_iterator_layer : public recursive_iterator_base<Iterator>,
  15. public RecursiveIterator_NextLayer {
  16. public:
  17. using super = RecursiveIterator_NextLayer;
  18. using layer = recursive_iterator_base<Iterator>;
  19. using key_type =
  20. typename std::tuple_element<0, typename layer::value_type>::type;
  21. protected:
  22. using recursive_category = continue_layer_tag_t;
  23. using next_value_type =
  24. typename next_layer_type<typename super::value_type,
  25. typename super::recursive_category>::type;
  26. using next_reference =
  27. typename next_layer_type<typename super::reference,
  28. typename super::recursive_category>::type;
  29. public:
  30. using value_type =
  31. decltype(std::tuple_cat(std::make_tuple(std::declval<key_type>()),
  32. std::declval<next_value_type>()));
  33. using reference = decltype(std::tuple_cat(
  34. std::tie(std::declval<key_type>()), std::declval<next_reference>()));
  35. using pointer = detail::arrow_proxy<reference>;
  36. using difference_type = std::ptrdiff_t;
  37. using iterator_category = std::forward_iterator_tag;
  38. public:
  39. flatten_iterator_layer() = default;
  40. explicit flatten_iterator_layer(layer v) : flatten_iterator_layer() {
  41. assign(v);
  42. update();
  43. }
  44. template <typename OIter, typename Rec>
  45. flatten_iterator_layer(flatten_iterator_layer<OIter, Rec> const & other)
  46. : layer(static_cast<recursive_iterator_base<OIter> const &>(other)),
  47. super(static_cast<Rec const &>(other)) {}
  48. /**
  49. * @brief Concatenate the key in this layer, with the dereferenced data from
  50. * the next.
  51. *
  52. * Due to the use of the next_layer_type metaprogramming, a type such as
  53. * std::map<K, std::vector<std::tuple<T1, T2, T3>>> would return a reference
  54. * of type std::tuple<K const &, std::tuple<T1, T2, T3>&>, preserving
  55. * sub-aggregates of pair/tuple type. Similarly, forward_as_tuple means
  56. * even a key-type of pair/tuple will not be unwrapped.
  57. */
  58. decltype(auto) operator*() const {
  59. return std::tuple_cat(std::forward_as_tuple(std::get<0>(layer::get())),
  60. next_reference(super::get()));
  61. }
  62. /**
  63. * Unimplemented because we return an inline constructed type, and tuple
  64. * can only be accessed through std::get anyway.
  65. */
  66. // auto operator->() const { return detail::arrow_proxy(**this); }
  67. void operator->() const;
  68. bool operator==(flatten_iterator_layer const & other) const {
  69. return (static_cast<layer const &>(*this) == other) &&
  70. (static_cast<super const &>(*this) == other);
  71. }
  72. protected:
  73. decltype(auto) get() const { return **this; }
  74. /**
  75. * @copydoc recursive_iterator_layer::next
  76. */
  77. void next() {
  78. super::next();
  79. update();
  80. }
  81. void update() {
  82. layer & self = static_cast<layer &>(*this);
  83. while (super::at_end() && !(++self).at_end()) {
  84. super::assign(make_end_aware_iterator(self->second));
  85. }
  86. }
  87. /**
  88. * @copydoc recursive_iterator_layer::assign
  89. */
  90. void assign(layer v) {
  91. static_cast<layer &>(*this) = v;
  92. if (!v.at_end()) { super::assign(make_end_aware_iterator(v->second)); }
  93. }
  94. using layer::at_end;
  95. };
  96. }}