// // concepts.h // iterator // // Created by Sam Jaffe on 9/20/25. // Copyright © 2025 Sam Jaffe. All rights reserved. // #pragma once #include #include #include namespace iterator { template concept implements_distance_to = requires(It const & it) { { it.distance_to(it) } -> std::integral; }; template struct infer_difference_type { using type = std::ptrdiff_t; }; template struct infer_difference_type { static const It & _it; using type = decltype(_it.distance_to(_it)); }; template using infer_difference_type_t = typename infer_difference_type::type; template concept difference_type_arg = std::convertible_to>; template struct infer_value_type { static const It & _it; using type = std::remove_cvref_t; }; template requires requires { typename It::value_type; } struct infer_value_type { using type = typename It::value_type; }; template using infer_value_type_t = infer_value_type::type; template concept not_same_as = not std::same_as; template concept has_sentinel = requires(It const & it) { typename It::sentinel_type; { it.at_end() } -> std::same_as; }; template concept sentinel_for = has_sentinel && requires(It const & it, S s) { { s - it } -> std::integral; }; template concept single_pass = bool(It::single_pass_iterator); template concept forward = requires(It & it) { { it.dereference() } -> not_same_as; { it.equal_to(it) } -> std::same_as; { it.increment() } -> std::same_as; }; template concept bidirectional = forward && requires(It & it) { { it.decrement() } -> std::same_as; }; template concept random_access = requires(It & it, infer_difference_type_t offset) { { it.dereference() } -> not_same_as; { it.equal_to(it) } -> std::same_as; { it.advance(offset) } -> std::same_as; }; template concept Char = std::same_as || std::same_as || std::same_as || std::same_as || std::same_as; template concept LegacyString = requires(S const & t) { { t.c_str() }; }; template concept StringViewCompat = Char && requires(S const & t) { { std::basic_string_view{t} }; }; template concept String = LegacyString || StringViewCompat; template concept Range = (not String) && std::ranges::range; template using iterator_t = decltype(std::begin(std::declval())); }