recursive_iterator_traits.hpp 2.0 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768
  1. #pragma once
  2. #include <iterator>
  3. #include <string>
  4. #include <tuple>
  5. #include <utility>
  6. namespace iterator { namespace detail {
  7. struct terminal_layer_tag_t;
  8. struct continue_layer_tag_t;
  9. template <typename> struct void_t { using type = void; };
  10. template <typename IterType>
  11. using value_iterator = decltype(std::begin(*std::declval<IterType>()));
  12. template <typename IterType>
  13. using mapped_iterator =
  14. decltype(std::begin(std::declval<IterType>()->second));
  15. /**
  16. * @class next_layer_type
  17. * @breif A template metaprogramming type for unifying associative and
  18. * non-associative containers.
  19. */
  20. template <typename V, typename Tag> struct next_layer_type {
  21. using type = std::tuple<V>;
  22. };
  23. template <typename V> struct next_layer_type<V, continue_layer_tag_t> {
  24. using type = V;
  25. };
  26. template <typename T, typename = void>
  27. struct is_associative : std::false_type {};
  28. template <typename T>
  29. struct is_associative<T, std::enable_if_t<std::is_const<
  30. typename T::value_type::first_type>::value>>
  31. : std::true_type {};
  32. template <typename T>
  33. using is_associative_t = std::enable_if_t<is_associative<T>::value>;
  34. /**
  35. * Type deduction guides for constructing recursive iterators.
  36. */
  37. enum class typeclass { TERMINAL, CONTAINER, ASSOCIATIVE_CONTAINER };
  38. template <typename T, typename = void> struct typeclass_t {
  39. static constexpr typeclass const value{typeclass::TERMINAL};
  40. };
  41. template <>
  42. struct typeclass_t<typename std::string::iterator> : typeclass_t<void> {};
  43. template <>
  44. struct typeclass_t<typename std::string::const_iterator> : typeclass_t<void> {
  45. };
  46. template <typename T>
  47. struct typeclass_t<T, typename void_t<value_iterator<T>>::type> {
  48. static constexpr typeclass const value{typeclass::CONTAINER};
  49. };
  50. template <typename T>
  51. struct typeclass_t<T, typename void_t<mapped_iterator<T>>::type> {
  52. static constexpr typeclass const value{typeclass::ASSOCIATIVE_CONTAINER};
  53. };
  54. }}