recursive_traits.h 1.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051
  1. #pragma once
  2. #include <iterator>
  3. #include "traits.h"
  4. namespace iterator::recursive {
  5. // Type deduction guides for constructing recursive iterators.
  6. enum class recursion_type { END, THRU, ASSOC };
  7. // Helpers for condensing type deductions
  8. template <typename It> using value = decltype(std::begin(*std::declval<It>()));
  9. template <typename It>
  10. using mapped = decltype(std::begin(std::declval<It>()->second));
  11. template <typename T> using val_key_t = typename T::value_type::first_type;
  12. // Type trait to identify value_type ~~ std::pair<K const, V>, which is
  13. // a safe bet towards 'this is an associative container type'
  14. template <typename T, typename = void>
  15. struct is_associative : std::false_type {};
  16. template <typename T>
  17. struct is_associative<T, std::enable_if_t<std::is_const_v<val_key_t<T>>>>
  18. : std::true_type {};
  19. template <typename T, typename = void> struct typeclass_t {
  20. static constexpr recursion_type const value{recursion_type::END};
  21. };
  22. template <typename T> struct is_string_iter : std::false_type {};
  23. template <> struct is_string_iter<std::string::iterator> : std::true_type {};
  24. template <>
  25. struct is_string_iter<std::string::const_iterator> : std::true_type {};
  26. template <typename T> constexpr bool is_string_iter_v = is_string_iter<T>{};
  27. template <typename T>
  28. struct typeclass_t<T, std::enable_if_t<!is_string_iter_v<value<T>>>> {
  29. constexpr static recursion_type value{recursion_type::THRU};
  30. };
  31. template <typename T>
  32. struct typeclass_t<T, std::enable_if_t<is_string_iter_v<value<T>>>> {
  33. constexpr static recursion_type value{recursion_type::END};
  34. };
  35. template <typename T> struct typeclass_t<T, detail::void_t<mapped<T>>> {
  36. constexpr static recursion_type value{recursion_type::ASSOC};
  37. };
  38. }