| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107 |
- #pragma once
- #include "recursive_iterator_base.hpp"
- #include "recursive_iterator_traits.hpp"
- namespace iterator { namespace detail {
- /**
- * @class flatten_iterator_layer
- * @brief A single layer for recursing down a nested collection. Represents
- * associative containers.
- *
- * @copydoc recursive_iterator_layer
- */
- template <typename Iterator, typename RecursiveIterator_NextLayer>
- class flatten_iterator_layer : public recursive_iterator_base<Iterator>,
- public RecursiveIterator_NextLayer {
- public:
- using super = RecursiveIterator_NextLayer;
- using layer = recursive_iterator_base<Iterator>;
- using key_type =
- typename std::tuple_element<0, typename layer::value_type>::type;
- protected:
- using recursive_category = continue_layer_tag_t;
- using next_value_type =
- typename next_layer_type<typename super::value_type,
- typename super::recursive_category>::type;
- using next_reference =
- typename next_layer_type<typename super::reference,
- typename super::recursive_category>::type;
- public:
- using value_type =
- decltype(std::tuple_cat(std::make_tuple(std::declval<key_type>()),
- std::declval<next_value_type>()));
- using reference = decltype(std::tuple_cat(
- std::tie(std::declval<key_type>()), std::declval<next_reference>()));
- using pointer = void;
- using difference_type = typename super::difference_type;
- using iterator_category = std::forward_iterator_tag;
- public:
- flatten_iterator_layer() = default;
- flatten_iterator_layer(layer v) : flatten_iterator_layer() {
- assign(v);
- update();
- }
- template <typename OIter, typename Rec>
- flatten_iterator_layer(flatten_iterator_layer<OIter, Rec> const & other)
- : layer(static_cast<recursive_iterator_base<OIter> const &>(other)),
- super(static_cast<Rec const &>(other)) {}
- /**
- * @brief Concatenate the key in this layer, with the dereferenced data from
- * the next.
- *
- * Due to the use of the next_layer_type metaprogramming, a type such as
- * std::map<K, std::vector<std::tuple<T1, T2, T3>>> would return a reference
- * of type std::tuple<K const &, std::tuple<T1, T2, T3>&>, preserving
- * sub-aggregates of pair/tuple type. Similarly, forward_as_tuple means
- * even a key-type of pair/tuple will not be unwrapped.
- */
- reference operator*() const {
- return std::tuple_cat(std::forward_as_tuple(std::get<0>(layer::get())),
- next_reference(super::get()));
- }
- /**
- * Unimplemented because we return an inline constructed type, and tuple
- * can only be accessed through std::get anyway.
- */
- pointer operator->() const;
- bool operator==(flatten_iterator_layer const & other) const {
- return layer::operator==(other) && super::operator==(other);
- }
- protected:
- reference get() const { return operator*(); }
- /**
- * @copydoc recursive_iterator_layer::next
- */
- void next() {
- super::next();
- update();
- }
- void update() {
- layer & self = static_cast<layer &>(*this);
- while (super::done() && !(++self).done()) {
- super::assign(make_end_aware_iterator(self->second));
- }
- }
- /**
- * @copydoc recursive_iterator_layer::assign
- */
- void assign(layer v) {
- static_cast<layer &>(*this) = v;
- if (!v.done()) { super::assign(make_end_aware_iterator(v->second)); }
- }
- bool done() const { return layer::done(); }
- };
- }}
|