facade_traits.h 3.0 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586
  1. //
  2. // facade_traits.h
  3. // iterator
  4. //
  5. // Created by Sam Jaffe on 4/1/23.
  6. // Copyright © 2023 Sam Jaffe. All rights reserved.
  7. //
  8. #pragma once
  9. #include <iterator>
  10. #include <type_traits>
  11. #include <iterator/detail/traits.h>
  12. #define _val(type) std::declval<type>()
  13. #define exists(expr) std::void_t<decltype(expr)>
  14. namespace iterator::detail {
  15. template <typename, typename = void> struct has_equal_to : std::false_type {};
  16. template <typename T>
  17. struct has_equal_to<T, exists(_val(T).equal_to(_val(T)))> : std::true_type {};
  18. template <typename, typename = void>
  19. struct has_distance_to : std::false_type {};
  20. template <typename T>
  21. struct has_distance_to<T, exists(_val(T).distance_to(_val(T)))>
  22. : std::true_type {};
  23. template <typename, typename = void>
  24. struct is_advanceable_iterator : std::false_type {};
  25. template <typename T>
  26. struct is_advanceable_iterator<T, exists(_val(T).advance({}))>
  27. : std::true_type {};
  28. template <typename, typename = void>
  29. struct is_single_pass_iterator : std::false_type {};
  30. template <typename T>
  31. struct is_single_pass_iterator<T, std::void_t<typename T::single_pass_iterator>>
  32. : std::true_type {};
  33. template <typename, typename = void> struct has_increment : std::false_type {};
  34. template <typename T>
  35. struct has_increment<T, exists(_val(T).increment())> : std::true_type {};
  36. template <typename, typename = void> struct has_decrement : std::false_type {};
  37. template <typename T>
  38. struct has_decrement<T, exists(_val(T).decrement())> : std::true_type {};
  39. template <typename, typename = void> struct distance_to {
  40. using type = std::ptrdiff_t;
  41. };
  42. template <typename T>
  43. struct distance_to<T, std::enable_if_t<has_distance_to<T>{}>> {
  44. using type = decltype(_val(T).distance_to(_val(T)));
  45. };
  46. template <typename T> using distance_to_t = typename distance_to<T>::type;
  47. template <typename T> constexpr bool has_equal_to_v = has_equal_to<T>{};
  48. template <typename T> constexpr bool has_distance_to_v = has_distance_to<T>{};
  49. template <typename T> constexpr bool has_increment_v = has_increment<T>{};
  50. template <typename T> constexpr bool has_decrement_v = has_decrement<T>{};
  51. template <typename T>
  52. constexpr bool is_advanceable_iterator_v = is_advanceable_iterator<T>{};
  53. template <typename It>
  54. constexpr bool is_single_pass_iterator_v = is_single_pass_iterator<It>{};
  55. template <typename It> struct facade_category {
  56. constexpr static bool has_random_access =
  57. has_distance_to_v<It> && is_advanceable_iterator_v<It>;
  58. constexpr static bool has_bidirectional =
  59. has_decrement_v<It> && has_increment_v<It> && has_equal_to_v<It>;
  60. using type = std::conditional_t<
  61. has_random_access, std::random_access_iterator_tag,
  62. std::conditional_t<has_bidirectional, std::bidirectional_iterator_tag,
  63. std::conditional_t<is_single_pass_iterator_v<It>,
  64. std::input_iterator_tag,
  65. std::forward_iterator_tag>>>;
  66. };
  67. template <typename It>
  68. using facade_category_t = typename facade_category<It>::type;
  69. }