#pragma once #include #include #include namespace util { template concept Number = std::integral || std::floating_point; template requires std::equality_comparable_with struct is_equal : public std::integral_constant { }; template inline constexpr auto is_equal_v = is_equal::value; template requires std::three_way_comparable_with struct cmp { constexpr static std::partial_ordering ordering = T <=> U; }; template inline constexpr auto cmp_v = cmp::ordering; template concept Compare = is_equal_v, ordering>; template concept Equal = is_equal_v; template concept all_same_as = (std::same_as && ...); template concept explicit_convertible_to = requires(const T ct, T t, const U &cu) { {t = cu}; { ct.operator U() } -> std::same_as; } || std::same_as; template concept explicit_convertible_to_any_of = (explicit_convertible_to, To> || ...); template struct is_explicit_convertible_to_any_of : std::bool_constant> {}; template concept explicit_convertible_to_integral = std::integral || explicit_convertible_to_any_of < std::remove_cv_t, bool, char, signed char, unsigned char, wchar_t, #ifdef __cpp_char8_t char8_t, #endif // __cpp_char8_t char16_t, char32_t, short, unsigned short, int, unsigned int, long, unsigned long, long long, unsigned long long > ; template concept explicit_convertible_to_floating_point = std::floating_point || explicit_convertible_to_any_of; template struct is_explicit_convertible : std::bool_constant> {}; template inline constexpr bool is_explicit_convertible_v = is_explicit_convertible::value; template concept with_return_type = requires(Fn fn, Args... args) { { fn(args...) } -> std::same_as; }; } // namespace util