79 lines
2.4 KiB
C++
79 lines
2.4 KiB
C++
#pragma once
|
|
|
|
#include <compare>
|
|
#include <concepts>
|
|
#include <type_traits>
|
|
|
|
namespace util {
|
|
|
|
template <typename T>
|
|
concept Number = std::integral<T> || std::floating_point<T>;
|
|
|
|
template <auto T, auto U>
|
|
requires std::equality_comparable_with<decltype(T), decltype(T)>
|
|
struct is_equal : public std::integral_constant<bool, T == U> {
|
|
};
|
|
|
|
template <auto T, auto U>
|
|
inline constexpr auto is_equal_v = is_equal<T, U>::value;
|
|
|
|
template <auto T, auto U>
|
|
requires std::three_way_comparable_with<decltype(T), decltype(T)>
|
|
struct cmp {
|
|
constexpr static std::partial_ordering ordering = T <=> U;
|
|
};
|
|
|
|
template <auto T, auto U> inline constexpr auto cmp_v = cmp<T, U>::ordering;
|
|
|
|
template <std::partial_ordering ordering, auto T, auto U>
|
|
concept Compare = is_equal_v<cmp_v<T, U>, ordering>;
|
|
|
|
template <auto T, auto U>
|
|
concept Equal = is_equal_v<T, U>;
|
|
|
|
template <typename T, typename... Pack>
|
|
concept all_same_as = (std::same_as<T, Pack> && ...);
|
|
|
|
template <typename T, typename U>
|
|
concept explicit_convertible_to = requires(const T ct, T t, const U &cu) {
|
|
{t = cu};
|
|
{ ct.operator U() } -> std::same_as<U>;
|
|
}
|
|
|| std::same_as<T, U>;
|
|
|
|
template <typename From, typename... To>
|
|
concept explicit_convertible_to_any_of =
|
|
(explicit_convertible_to<std::remove_cv_t<From>, To> || ...);
|
|
|
|
template <typename From, typename... To>
|
|
struct is_explicit_convertible_to_any_of
|
|
: std::bool_constant<explicit_convertible_to_any_of<From, To...>> {};
|
|
|
|
template <typename T>
|
|
concept explicit_convertible_to_integral =
|
|
std::integral<T> || explicit_convertible_to_any_of < std::remove_cv_t<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 <typename T>
|
|
concept explicit_convertible_to_floating_point = std::floating_point<T> ||
|
|
explicit_convertible_to_any_of<T, float, double, long double>;
|
|
|
|
template <typename From, typename To>
|
|
struct is_explicit_convertible
|
|
: std::bool_constant<explicit_convertible_to<From, To>> {};
|
|
|
|
template <typename From, typename To>
|
|
inline constexpr bool is_explicit_convertible_v =
|
|
is_explicit_convertible<From, To>::value;
|
|
|
|
template <typename Fn, typename R, typename... Args>
|
|
concept with_return_type = requires(Fn fn, Args... args) {
|
|
{ fn(args...) } -> std::same_as<R>;
|
|
};
|
|
|
|
} // namespace util
|