| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051 |
- #pragma once
- #include <iterator>
- #include "traits.h"
- namespace iterator::recursive {
- // Type deduction guides for constructing recursive iterators.
- enum class recursion_type { END, THRU, ASSOC };
- // Helpers for condensing type deductions
- template <typename It> using value = decltype(std::begin(*std::declval<It>()));
- template <typename It>
- using mapped = decltype(std::begin(std::declval<It>()->second));
- template <typename T> using val_key_t = typename T::value_type::first_type;
- // 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_v<val_key_t<T>>>>
- : std::true_type {};
- template <typename T, typename = void> struct typeclass_t {
- static constexpr recursion_type const value{recursion_type::END};
- };
- template <typename T> struct is_string_iter : std::false_type {};
- template <> struct is_string_iter<std::string::iterator> : std::true_type {};
- template <>
- struct is_string_iter<std::string::const_iterator> : std::true_type {};
- template <typename T> constexpr bool is_string_iter_v = is_string_iter<T>{};
- template <typename T>
- struct typeclass_t<T, std::enable_if_t<!is_string_iter_v<value<T>>>> {
- constexpr static recursion_type value{recursion_type::THRU};
- };
- template <typename T>
- struct typeclass_t<T, std::enable_if_t<is_string_iter_v<value<T>>>> {
- constexpr static recursion_type value{recursion_type::END};
- };
- template <typename T> struct typeclass_t<T, detail::void_t<mapped<T>>> {
- constexpr static recursion_type value{recursion_type::ASSOC};
- };
- }
|