|
|
@@ -3,72 +3,34 @@
|
|
|
#include "../end_aware_iterator.hpp"
|
|
|
#include "recursive_iterator_traits.hpp"
|
|
|
|
|
|
-namespace iterator { namespace detail {
|
|
|
-
|
|
|
- template <typename Iterator, typename = void> class recursive_iterator_base;
|
|
|
-
|
|
|
+namespace iterator::detail {
|
|
|
/**
|
|
|
* @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;
|
|
|
-
|
|
|
- protected:
|
|
|
- decltype(auto) 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, is_associative_t<Iterator>>
|
|
|
- : public end_aware_iterator<Iterator> {
|
|
|
+ class recursive_iterator_base : 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;
|
|
|
+ using recursive_category =
|
|
|
+ std::conditional_t<detail::is_associative<Iterator>{},
|
|
|
+ continue_layer_tag_t, 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;
|
|
|
|
|
|
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.
|
|
|
- */
|
|
|
- auto get() const { return std::tie((**this).first, (**this).second); }
|
|
|
+ decltype(auto) get() const {
|
|
|
+ if constexpr (detail::is_associative<Iterator>{}) {
|
|
|
+ return std::tie((**this).first, (**this).second);
|
|
|
+ } else {
|
|
|
+ return **this;
|
|
|
+ }
|
|
|
+ }
|
|
|
};
|
|
|
-
|
|
|
-}}
|
|
|
+}
|