|
|
@@ -9,83 +9,36 @@
|
|
|
|
|
|
#include "iterator_fwd.hpp"
|
|
|
|
|
|
-#include <iterator>
|
|
|
#include <string>
|
|
|
#include <tuple>
|
|
|
#include <utility>
|
|
|
|
|
|
-#include "detail/traits.h"
|
|
|
+#include "detail/recursive_traits.h"
|
|
|
#include "end_aware_iterator.hpp"
|
|
|
#include "facade.h"
|
|
|
|
|
|
-namespace iterator::recursive {
|
|
|
- // Helpers for condensing type deductions
|
|
|
- template <typename IterType>
|
|
|
- using value = decltype(std::begin(*std::declval<IterType>()));
|
|
|
-
|
|
|
- template <typename IterType>
|
|
|
- using mapped = decltype(std::begin(std::declval<IterType>()->second));
|
|
|
-
|
|
|
- // Type trait to identify value_type ~~ std::pair<K const, V>, which is
|
|
|
- // a safe bet towards 'this is an associative container type'
|
|
|
- template <typename T, typename = void>
|
|
|
- struct is_associative : std::false_type {};
|
|
|
- template <typename T>
|
|
|
- struct is_associative<T, std::enable_if_t<std::is_const<
|
|
|
- typename T::value_type::first_type>::value>>
|
|
|
- : std::true_type {};
|
|
|
-
|
|
|
- // Type deduction guides for constructing recursive iterators.
|
|
|
- enum class typeclass { TERMINAL, CONTAINER, ASSOCIATIVE_CONTAINER };
|
|
|
-
|
|
|
- template <typename T, typename = void> struct typeclass_t {
|
|
|
- static constexpr typeclass const value{typeclass::TERMINAL};
|
|
|
- };
|
|
|
-
|
|
|
- template <typename T> struct is_string_iterator : std::false_type {};
|
|
|
- template <>
|
|
|
- struct is_string_iterator<std::string::iterator> : std::true_type {};
|
|
|
- template <>
|
|
|
- struct is_string_iterator<std::string::const_iterator> : std::true_type {};
|
|
|
-
|
|
|
- template <typename T>
|
|
|
- struct typeclass_t<T,
|
|
|
- std::enable_if_t<!is_string_iterator<value<T>>::value>> {
|
|
|
- static constexpr typeclass const value{typeclass::CONTAINER};
|
|
|
- };
|
|
|
-
|
|
|
- template <typename T>
|
|
|
- struct typeclass_t<T, std::enable_if_t<is_string_iterator<value<T>>::value>> {
|
|
|
- static constexpr typeclass const value{typeclass::TERMINAL};
|
|
|
- };
|
|
|
-
|
|
|
- template <typename T> struct typeclass_t<T, detail::void_t<mapped<T>>> {
|
|
|
- static constexpr typeclass const value{typeclass::ASSOCIATIVE_CONTAINER};
|
|
|
- };
|
|
|
-}
|
|
|
-
|
|
|
namespace iterator::recursive {
|
|
|
template <size_t N, size_t I = 1> struct bounded {
|
|
|
template <typename It>
|
|
|
- static constexpr typeclass const value =
|
|
|
- I == N ? typeclass::TERMINAL : typeclass_t<It>::value;
|
|
|
+ static constexpr recursion_type const value =
|
|
|
+ I == N ? recursion_type::END : typeclass_t<It>::value;
|
|
|
using next = std::conditional_t<I == N, void, bounded<N, I + 1>>;
|
|
|
static constexpr size_t size = N;
|
|
|
};
|
|
|
|
|
|
struct unbounded {
|
|
|
template <typename It>
|
|
|
- static constexpr typeclass const value = typeclass_t<It>::value;
|
|
|
+ static constexpr recursion_type const value = typeclass_t<It>::value;
|
|
|
using next = unbounded;
|
|
|
static constexpr size_t size = std::numeric_limits<size_t>::max();
|
|
|
};
|
|
|
|
|
|
template <typename It, typename Bnd = unbounded,
|
|
|
- typeclass = Bnd::template value<It>>
|
|
|
+ recursion_type = Bnd::template value<It>>
|
|
|
struct tuple;
|
|
|
|
|
|
template <typename It, typename Bnd>
|
|
|
- struct tuple<It, Bnd, typeclass::TERMINAL> {
|
|
|
+ struct tuple<It, Bnd, recursion_type::END> {
|
|
|
using iter = std::tuple<end_aware_iterator<It>>;
|
|
|
decltype(auto) get(It iter) const {
|
|
|
if constexpr (is_associative<It>{}) {
|
|
|
@@ -100,7 +53,7 @@ namespace iterator::recursive {
|
|
|
using tuple_cat_t = decltype(std::tuple_cat(std::declval<Ts>()...));
|
|
|
|
|
|
template <typename It, typename Bnd>
|
|
|
- struct tuple<It, Bnd, typeclass::CONTAINER> {
|
|
|
+ struct tuple<It, Bnd, recursion_type::THRU> {
|
|
|
using next = decltype(std::begin(*std::declval<It>()));
|
|
|
using iter = tuple_cat_t<std::tuple<end_aware_iterator<It>>,
|
|
|
typename tuple<next, typename Bnd::next>::iter>;
|
|
|
@@ -108,7 +61,7 @@ namespace iterator::recursive {
|
|
|
};
|
|
|
|
|
|
template <typename It, typename Bnd>
|
|
|
- struct tuple<It, Bnd, typeclass::ASSOCIATIVE_CONTAINER> {
|
|
|
+ struct tuple<It, Bnd, recursion_type::ASSOC> {
|
|
|
using next = decltype(std::begin(std::declval<It>()->second));
|
|
|
using iter = tuple_cat_t<std::tuple<end_aware_iterator<It>>,
|
|
|
typename tuple<next, typename Bnd::next>::iter>;
|
|
|
@@ -173,7 +126,7 @@ namespace iterator::recursive {
|
|
|
// iteration to be had.
|
|
|
auto it = std::get<I>(impl_);
|
|
|
if constexpr (I == size - 1) {
|
|
|
- return tuple<decltype(it), unbounded, typeclass::TERMINAL>{}.get(it);
|
|
|
+ return tuple<decltype(it), unbounded, recursion_type::END>{}.get(it);
|
|
|
} else {
|
|
|
// Implemented as a recursive function instead of a parameter-pack
|
|
|
// because OSX has a compiler bug regarding certain forms of parameter
|