| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123 |
- //
- // concepts.h
- // iterator
- //
- // Created by Sam Jaffe on 9/20/25.
- // Copyright © 2025 Sam Jaffe. All rights reserved.
- //
- #pragma once
- #include <concepts>
- #include <ranges>
- #include <string_view>
- #include <tuple>
- #include <type_traits>
- namespace iterator {
- template <typename It>
- concept implements_distance_to = requires(It const & it) {
- { it.distance_to(it) } -> std::integral;
- };
- template <typename> struct infer_difference_type {
- using type = std::ptrdiff_t;
- };
- template <implements_distance_to It> struct infer_difference_type<It> {
- static const It & _it;
- using type = decltype(_it.distance_to(_it));
- };
- template <typename It>
- using infer_difference_type_t = typename infer_difference_type<It>::type;
- template <typename D, typename It>
- concept difference_type_arg =
- std::convertible_to<D, infer_difference_type_t<It>>;
- template <typename It> struct infer_value_type {
- static const It & _it;
- using type = std::remove_cvref_t<decltype(*_it)>;
- };
- template <typename It>
- requires requires { typename It::value_type; }
- struct infer_value_type<It> {
- using type = typename It::value_type;
- };
- template <typename It> using infer_value_type_t = infer_value_type<It>::type;
- template <typename T, typename U>
- concept not_same_as = not std::same_as<T, U>;
- template <typename It>
- concept has_sentinel = requires(It const & it) {
- typename It::sentinel_type;
- { it.at_end() } -> std::same_as<bool>;
- };
- template <typename It, typename S>
- concept sentinel_for = has_sentinel<It> && requires(It const & it, S s) {
- { s - it } -> std::integral;
- };
- template <typename It>
- concept single_pass = bool(It::single_pass_iterator);
- template <typename It>
- concept forward = requires(It & it) {
- { it.dereference() } -> not_same_as<void>;
- { it.equal_to(it) } -> std::same_as<bool>;
- { it.increment() } -> std::same_as<void>;
- };
- template <typename It>
- concept bidirectional = forward<It> && requires(It & it) {
- { it.decrement() } -> std::same_as<void>;
- };
- template <typename It>
- concept random_access = requires(It & it, infer_difference_type_t<It> offset) {
- { it.dereference() } -> not_same_as<void>;
- { it.equal_to(it) } -> std::same_as<bool>;
- { it.advance(offset) } -> std::same_as<void>;
- };
- template <typename C>
- concept Char = std::same_as<C, char> || std::same_as<C, wchar_t> ||
- std::same_as<C, char16_t> || std::same_as<C, char32_t> ||
- std::same_as<C, char8_t>;
- template <typename S>
- concept LegacyString = requires(S const & t) {
- { t.c_str() };
- };
- template <typename S>
- concept StringViewCompat =
- Char<typename S::value_type> && requires(S const & t) {
- { std::basic_string_view{t} };
- };
- template <typename S>
- concept String = LegacyString<S> || StringViewCompat<S>;
- template <typename C>
- concept Range = (not String<C>) && std::ranges::range<C>;
- template <typename V>
- concept Assoc =
- std::is_const_v<std::remove_reference_t<std::tuple_element_t<0, V>>>;
- template <typename V>
- concept AssocRange = Assoc<V> && (std::tuple_size_v<V> == 2) &&
- Range<std::decay_t<std::tuple_element_t<1, V>>>;
- template <typename C>
- using iterator_t = decltype(std::begin(std::declval<C &>()));
- template <typename... Ts>
- using tuple_cat_t = decltype(std::tuple_cat(std::declval<Ts>()...));
- }
|