traits.h 2.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293
  1. #pragma once
  2. #include <algorithm>
  3. #include <iterator>
  4. #include <type_traits>
  5. #include <iterator/forwards.h>
  6. #include <iterator/detail/macro.h>
  7. // Section: Non-Dependant Typedef Helpers
  8. namespace iterator::detail {
  9. template <typename Iter>
  10. using category_t = typename std::iterator_traits<Iter>::iterator_category;
  11. template <typename C> using iter = decltype(std::begin(std::declval<C>()));
  12. }
  13. namespace iterator::detail {
  14. // Type Helper for identifying container-like objects
  15. template <typename C, typename = void> struct is_container : std::false_type {};
  16. template <typename C>
  17. struct is_container<C, std::void_t<iter<C>>> : std::true_type {};
  18. template <typename It, typename = void>
  19. struct has_sentinel_type : std::false_type {};
  20. template <typename It>
  21. struct has_sentinel_type<It, std::void_t<typename It::sentinel_type>>
  22. : std::true_type {};
  23. }
  24. // Mappings between iterator::category enum and iterator_category tags
  25. namespace iterator::detail {
  26. template <typename Tag, category Limit = static_cast<category>(~0)>
  27. struct category_for {
  28. constexpr static category value = category::single_pass;
  29. };
  30. template <category Limit>
  31. struct category_for<std::forward_iterator_tag, Limit> {
  32. constexpr static category value = std::min(category::forward, Limit);
  33. };
  34. template <category Limit>
  35. struct category_for<std::bidirectional_iterator_tag, Limit> {
  36. constexpr static category value = std::min(category::bidirectional, Limit);
  37. };
  38. template <category Limit>
  39. struct category_for<std::random_access_iterator_tag, Limit> {
  40. constexpr static category value = std::min(category::random_access, Limit);
  41. };
  42. template <category> struct tag_for;
  43. template <> struct tag_for<category::single_pass> {
  44. using type = std::input_iterator_tag;
  45. };
  46. template <category> struct tag_for;
  47. template <> struct tag_for<category::forward> {
  48. using type = std::forward_iterator_tag;
  49. };
  50. template <category> struct tag_for;
  51. template <> struct tag_for<category::bidirectional> {
  52. using type = std::bidirectional_iterator_tag;
  53. };
  54. template <category> struct tag_for;
  55. template <> struct tag_for<category::random_access> {
  56. using type = std::random_access_iterator_tag;
  57. };
  58. }
  59. namespace iterator::detail {
  60. template <typename C> constexpr bool is_container_v = is_container<C>{};
  61. template <typename Iter>
  62. constexpr bool is_rvalue_iterator_v = !std::is_reference_v<DEREF_TYPE(Iter)>;
  63. template <typename It>
  64. constexpr bool has_sentinel_type_v = has_sentinel_type<It>{};
  65. template <typename It, typename S>
  66. using sentinel_type = std::conditional_t<std::is_same_v<It, S>, sentinel_t, S>;
  67. template <typename It, category Limit = static_cast<category>(~0)>
  68. constexpr auto category_for_v = category_for<category_t<It>, Limit>::value;
  69. template <typename It>
  70. using tag_for_t = typename tag_for<It::category_enum>::type;
  71. }
  72. #include <iterator/detail/undef.h>