#pragma once #include #include #include #include #include "../iterator_fwd.hpp" namespace iterator { namespace detail { template class flatten_iterator_layer; template class recursive_iterator_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_iterator = decltype(std::begin(*std::declval())); template using mapped_iterator = 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 {}; template using is_associative_t = std::enable_if_t::value>; // Type deduction guides for constructing recursive iterators. enum class typeclass { TERMINAL, CONTAINER, ASSOCIATIVE_CONTAINER }; template struct void_t { using type = void; }; 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< T, std::enable_if_t>::value>> { static constexpr typeclass const value{typeclass::CONTAINER}; }; template struct typeclass_t< T, std::enable_if_t>::value>> { static constexpr typeclass const value{typeclass::TERMINAL}; }; template struct typeclass_t>::type> { 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, recursive_iterator_layer> { using type = end_aware_iterator; }; template struct accessor<0, flatten_iterator_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; }; }}