|
|
@@ -21,10 +21,12 @@
|
|
|
#include <iterator/detail/macro.h>
|
|
|
|
|
|
namespace iterator {
|
|
|
-template <typename Tuple, typename Indices> class recursive_iterator_base;
|
|
|
-template <typename... It, size_t... Is>
|
|
|
-class recursive_iterator_base<std::tuple<It...>, std::index_sequence<Is...>>
|
|
|
- : public std::tuple<It...> {
|
|
|
+template <typename Tuple, typename Projs, typename Indices>
|
|
|
+class recursive_iterator_base;
|
|
|
+template <typename... It, typename... Projs, size_t... Is>
|
|
|
+class recursive_iterator_base<std::tuple<It...>, detail::Projections<Projs...>,
|
|
|
+ std::index_sequence<Is...>>
|
|
|
+ : public std::tuple<It...>, private detail::Projections<Projs...> {
|
|
|
public:
|
|
|
static constexpr size_t LastIndex = sizeof...(It) - 1;
|
|
|
template <size_t I>
|
|
|
@@ -58,7 +60,10 @@ public:
|
|
|
|
|
|
protected:
|
|
|
recursive_iterator_base() = default;
|
|
|
- recursive_iterator_base(iterator_type<0> iter) { assign<0>(iter); }
|
|
|
+ recursive_iterator_base(iterator_type<0> iter, Projs... projs)
|
|
|
+ : detail::Projections<Projs...>(projs...) {
|
|
|
+ assign<0>(iter);
|
|
|
+ }
|
|
|
|
|
|
private:
|
|
|
template <size_t I = LastIndex> bool increment() {
|
|
|
@@ -76,10 +81,12 @@ private:
|
|
|
template <size_t I> decltype(auto) get() const {
|
|
|
auto iter = std::get<I>(*this);
|
|
|
if constexpr (I + 1 == sizeof...(It)) {
|
|
|
- if constexpr (Assoc<value_type<I>>) {
|
|
|
- return std::tie(iter->first, iter->second);
|
|
|
+ auto && rval = (*this)(*iter, std::integral_constant<size_t, I>{});
|
|
|
+ if constexpr (Assoc<std::decay_t<decltype(rval)>>) {
|
|
|
+ // Needed for tuple-cat to preserve references
|
|
|
+ return std::tie(rval.first, rval.second);
|
|
|
} else {
|
|
|
- return std::tie(*iter);
|
|
|
+ return std::tie(rval); // Cannot wrap tie(pair) and expect it to work
|
|
|
}
|
|
|
} else if constexpr (Assoc<value_type<I>>) {
|
|
|
return std::tie(iter->first);
|
|
|
@@ -91,7 +98,9 @@ private:
|
|
|
template <size_t I, typename T> void assign(end_aware_iterator<T> it) {
|
|
|
std::get<I>(*this) = it;
|
|
|
if constexpr (I < LastIndex) {
|
|
|
- if (!it.at_end()) { assign<I + 1>(*it); }
|
|
|
+ if (!it.at_end()) {
|
|
|
+ assign<I + 1>((*this)(*it, std::integral_constant<size_t, I>{}));
|
|
|
+ }
|
|
|
}
|
|
|
}
|
|
|
|
|
|
@@ -99,7 +108,7 @@ private:
|
|
|
if constexpr (Range<T>) {
|
|
|
assign<I>(end_aware_iterator(std::forward<T>(value)));
|
|
|
} else {
|
|
|
- assign<I>(value.second);
|
|
|
+ assign<I>(std::get<1>(value));
|
|
|
}
|
|
|
}
|
|
|
};
|
|
|
@@ -116,7 +125,7 @@ struct recursive_iterator_helper {
|
|
|
static constexpr auto extent = std::tuple_size_v<iterator_tuple>;
|
|
|
using indices = decltype(std::make_index_sequence<extent>());
|
|
|
|
|
|
- using type = recursive_iterator_base<iterator_tuple, indices>;
|
|
|
+ using type = recursive_iterator_base<iterator_tuple, Projections, indices>;
|
|
|
};
|
|
|
|
|
|
/**
|
|
|
@@ -162,7 +171,7 @@ recursive_iterator(Range &, MaxDepth)
|
|
|
-> recursive_iterator<iterator_t<Range>, MaxDepth>;
|
|
|
template <typename Range>
|
|
|
recursive_iterator(Range &) -> recursive_iterator<iterator_t<Range>, unbounded>;
|
|
|
-}
|
|
|
+} // namespace iterator
|
|
|
|
|
|
namespace std {
|
|
|
template <size_t I, typename It, typename MaxDepth>
|
|
|
@@ -170,7 +179,7 @@ auto get(::iterator::recursive_iterator<It, MaxDepth> const & iter) {
|
|
|
using return_type = std::decay_t<decltype(iter)>::template iterator_type<I>;
|
|
|
return static_cast<return_type>(iter);
|
|
|
}
|
|
|
-}
|
|
|
+} // namespace std
|
|
|
|
|
|
namespace iterator::views {
|
|
|
template <size_t N>
|
|
|
@@ -190,6 +199,6 @@ struct recursive_fn : std::ranges::range_adaptor_closure<recursive_fn> {
|
|
|
|
|
|
template <size_t N> constexpr recursive_n_fn<N> recursive_n{};
|
|
|
constexpr recursive_fn recursive;
|
|
|
-}
|
|
|
+} // namespace iterator::views
|
|
|
|
|
|
#include <iterator/detail/undef.h>
|