flatten_iterator_layer.hpp 3.6 KB

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