cpp-utils/include/concepts/traits.hpp
2022-06-23 17:26:19 +01:00

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