concepts.h 1.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778
  1. //
  2. // concepts.h
  3. // iterator
  4. //
  5. // Created by Sam Jaffe on 9/20/25.
  6. // Copyright © 2025 Sam Jaffe. All rights reserved.
  7. //
  8. #pragma once
  9. #include <concepts>
  10. namespace iterator {
  11. template <typename It>
  12. concept implements_distance_to = requires(It const &it) {
  13. { it.distance_to(it) } -> std::integral;
  14. };
  15. template <typename> struct infer_difference_type {
  16. using type = std::ptrdiff_t;
  17. };
  18. template <implements_distance_to It>
  19. struct infer_difference_type<It> {
  20. static const It& _it;
  21. using type = decltype(_it.distance_to(_it));
  22. };
  23. template <typename It>
  24. using infer_difference_type_t = typename infer_difference_type<It>::type;
  25. template <typename D, typename It>
  26. concept difference_type_arg = std::convertible_to<D, infer_difference_type_t<It>>;
  27. template <typename It>
  28. struct infer_value_type {
  29. static const It& _it;
  30. using type = std::remove_cvref_t<decltype(*_it)>;
  31. };
  32. template <typename It>
  33. requires requires { typename It::value_type; }
  34. struct infer_value_type<It> {
  35. using type = typename It::value_type;
  36. };
  37. template <typename It>
  38. using infer_value_type_t = infer_value_type<It>::type;
  39. template <typename T, typename U> concept not_same_as = not std::same_as<T, U>;
  40. template <typename It>
  41. concept has_sentinel = requires(It const &it) {
  42. { it.as_end() } -> std::same_as<bool>;
  43. };
  44. template <typename It>
  45. concept single_pass = bool(It::single_pass_iterator);
  46. template <typename It>
  47. concept forward = requires(It &it) {
  48. { it.dereference() } -> not_same_as<void>;
  49. { it.equal_to(it) } -> std::same_as<bool>;
  50. { it.increment() } -> std::same_as<void>;
  51. };
  52. template <typename It>
  53. concept bidirectional = forward<It> && requires(It &it) {
  54. { it.decrement() } -> std::same_as<void>;
  55. };
  56. template <typename It>
  57. concept random_access = requires(It &it, infer_difference_type_t<It> offset) {
  58. { it.dereference() } -> not_same_as<void>;
  59. { it.equal_to(it) } -> std::same_as<bool>;
  60. { it.advance(offset) } -> std::same_as<void>;
  61. };
  62. }