#pragma once #include #include #include #include #include "../detail/traits.h" #include "../iterator_fwd.hpp" namespace iterator::recursive { template class flatten_layer; template class layer; // Helper struct for dealing with merging output from associative and // non-associative containers. // TODO: This seems unnecessarily verbose t.b.h. struct terminal_layer_tag_t; struct continue_layer_tag_t; template struct next_layer_type { using type = std::tuple; }; template struct next_layer_type { using type = V; }; // Helpers for condensing type deductions template using value = decltype(std::begin(*std::declval())); template using mapped = decltype(std::begin(std::declval()->second)); // Type trait to identify value_type ~~ std::pair, which is // a safe bet towards 'this is an associative container type' template struct is_associative : std::false_type {}; template struct is_associative::value>> : std::true_type {}; // Type deduction guides for constructing recursive iterators. enum class typeclass { TERMINAL, CONTAINER, ASSOCIATIVE_CONTAINER }; template struct typeclass_t { static constexpr typeclass const value{typeclass::TERMINAL}; }; template struct is_string_iterator : std::false_type {}; template <> struct is_string_iterator : std::true_type {}; template <> struct is_string_iterator : std::true_type {}; template struct typeclass_t>::value>> { static constexpr typeclass const value{typeclass::CONTAINER}; }; template struct typeclass_t>::value>> { static constexpr typeclass const value{typeclass::TERMINAL}; }; template struct typeclass_t>> { static constexpr typeclass const value{typeclass::ASSOCIATIVE_CONTAINER}; }; // Accessor templates for invoking std::get template struct accessor; template struct accessor<0, end_aware_iterator> { using type = end_aware_iterator; }; template struct accessor<0, layer> { using type = end_aware_iterator; }; template struct accessor<0, flatten_layer> { using type = end_aware_iterator; }; template struct accessor<0, It> { using type = typename accessor<0, typename It::super>::type; }; template struct accessor::type> { using type = typename accessor::type; }; template struct accessor, typename std::enable_if::type> { using type = typename accessor::type; }; template struct accessor, typename std::enable_if::type> { using type = typename accessor::type; }; }