traits.hpp 3.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109
  1. #pragma once
  2. #include <iterator>
  3. #include <string>
  4. #include <tuple>
  5. #include <utility>
  6. #include "../detail/traits.h"
  7. #include "../iterator_fwd.hpp"
  8. namespace iterator::recursive {
  9. template <typename Iterator, typename Next> class flatten_layer;
  10. template <typename Iterator, typename Next> class layer;
  11. // Helper struct for dealing with merging output from associative and
  12. // non-associative containers.
  13. // TODO: This seems unnecessarily verbose t.b.h.
  14. struct terminal_layer_tag_t;
  15. struct continue_layer_tag_t;
  16. template <typename V, typename Tag> struct next_layer_type {
  17. using type = std::tuple<V>;
  18. };
  19. template <typename V> struct next_layer_type<V, continue_layer_tag_t> {
  20. using type = V;
  21. };
  22. // Helpers for condensing type deductions
  23. template <typename IterType>
  24. using value = decltype(std::begin(*std::declval<IterType>()));
  25. template <typename IterType>
  26. using mapped = decltype(std::begin(std::declval<IterType>()->second));
  27. // Type trait to identify value_type ~~ std::pair<K const, V>, which is
  28. // a safe bet towards 'this is an associative container type'
  29. template <typename T, typename = void>
  30. struct is_associative : std::false_type {};
  31. template <typename T>
  32. struct is_associative<T, std::enable_if_t<std::is_const<
  33. typename T::value_type::first_type>::value>>
  34. : std::true_type {};
  35. // Type deduction guides for constructing recursive iterators.
  36. enum class typeclass { TERMINAL, CONTAINER, ASSOCIATIVE_CONTAINER };
  37. template <typename T, typename = void> struct typeclass_t {
  38. static constexpr typeclass const value{typeclass::TERMINAL};
  39. };
  40. template <typename T> struct is_string_iterator : std::false_type {};
  41. template <>
  42. struct is_string_iterator<std::string::iterator> : std::true_type {};
  43. template <>
  44. struct is_string_iterator<std::string::const_iterator> : std::true_type {};
  45. template <typename T>
  46. struct typeclass_t<T,
  47. std::enable_if_t<!is_string_iterator<value<T>>::value>> {
  48. static constexpr typeclass const value{typeclass::CONTAINER};
  49. };
  50. template <typename T>
  51. struct typeclass_t<T, std::enable_if_t<is_string_iterator<value<T>>::value>> {
  52. static constexpr typeclass const value{typeclass::TERMINAL};
  53. };
  54. template <typename T> struct typeclass_t<T, detail::void_t<mapped<T>>> {
  55. static constexpr typeclass const value{typeclass::ASSOCIATIVE_CONTAINER};
  56. };
  57. // Accessor templates for invoking std::get
  58. template <std::size_t I, typename It, typename = void> struct accessor;
  59. template <typename It> struct accessor<0, end_aware_iterator<It>> {
  60. using type = end_aware_iterator<It>;
  61. };
  62. template <typename It, typename Rec> struct accessor<0, layer<It, Rec>> {
  63. using type = end_aware_iterator<It>;
  64. };
  65. template <typename It, typename Rec>
  66. struct accessor<0, flatten_layer<It, Rec>> {
  67. using type = end_aware_iterator<It>;
  68. };
  69. template <typename It> struct accessor<0, It> {
  70. using type = typename accessor<0, typename It::super>::type;
  71. };
  72. template <std::size_t I, typename It>
  73. struct accessor<I, It, typename std::enable_if<I != 0>::type> {
  74. using type = typename accessor<I, typename It::super>::type;
  75. };
  76. template <std::size_t I, typename It, typename Rec>
  77. struct accessor<I, layer<It, Rec>, typename std::enable_if<I != 0>::type> {
  78. using type = typename accessor<I - 1, Rec>::type;
  79. };
  80. template <std::size_t I, typename It, typename Rec>
  81. struct accessor<I, flatten_layer<It, Rec>,
  82. typename std::enable_if<I != 0>::type> {
  83. using type = typename accessor<I - 1, Rec>::type;
  84. };
  85. }