| 1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586 |
- #pragma once
- #include "../end_aware_iterator.hpp"
- #include "recursive_iterator_traits.hpp"
- namespace iterator { namespace detail {
- template <typename Iterator, typename = void> class recursive_iterator_base;
- /**
- * @class recursive_iterator_base
- * @brief A thin wrapper around end_aware_iterator for the purposes of
- * template metaprogramming.
- */
- template <typename Iterator, typename>
- class recursive_iterator_base : public end_aware_iterator<Iterator> {
- public:
- using super = end_aware_iterator<Iterator>;
- protected:
- using recursive_category = terminal_layer_tag_t;
- public:
- using super::super;
- recursive_iterator_base(super const & iter) : super(iter) {}
- recursive_iterator_base(super && iter) : super(std::move(iter)) {}
- recursive_iterator_base() = default;
- operator super() const { return *this; }
- protected:
- typename super::reference get() const { return super::operator*(); }
- };
- /**
- * @class recursive_iterator_base
- * @brief An SFINAE specialization of recursive_iterator_base for associative
- * containers
- *
- * Because it is possible for recursive iterator to step over multiple layers
- * of associative containers, the return type is made into a tuple, so that
- * the caller does not need to write something like
- * `it->second.second.second'. Instead, the return type is a tuple of
- * references, so that the caller can write code like `std::get<3>(*it)'.
- *
- * For example, the ref type for std::map<int, std::map<float, double> >
- * with this would be std::tuple<int const&, float const&, double &>.
- */
- template <typename Iterator>
- class recursive_iterator_base<
- Iterator,
- typename std::enable_if<std::is_const<typename end_aware_iterator<
- Iterator>::value_type::first_type>::value>::type>
- : public end_aware_iterator<Iterator> {
- public:
- using super = end_aware_iterator<Iterator>;
- using first_type = decltype((std::declval<Iterator>()->first));
- using second_type = decltype((std::declval<Iterator>()->second));
- protected:
- using recursive_category = continue_layer_tag_t;
- public:
- using value_type = std::tuple<first_type, second_type>;
- using reference = std::tuple<first_type &, second_type &>;
- public:
- using super::super;
- recursive_iterator_base(super const & iter) : super(iter) {}
- recursive_iterator_base(super && iter) : super(std::move(iter)) {}
- recursive_iterator_base() = default;
- operator super() const { return *this; }
- protected:
- /**
- * An alternative function to operator*(), which allows single layer
- * recursive iterators (on associative containers) to return the
- * underlying value/reference type, and nested containers to propogate
- * a tuple or a pair as necessary.
- */
- reference get() const {
- auto & pair = super::operator*();
- return std::tie(pair.first, pair.second);
- }
- };
- }}
|