1 #ifndef EAGINE_IS_WITHIN_LIMITS_HPP
9 #define EAGINE_IS_WITHIN_LIMITS_HPP
17 #include <type_traits>
21 #if defined(__clang__)
22 EAGINE_DIAG_OFF(shorten-64-to-32)
23 #elif defined(__GNUC__)
24 EAGINE_DIAG_OFF(
sign-compare)
29 template <
typename Dst,
typename Src>
30 struct implicitly_within_limits
32 ((std::is_integral_v<Dst> && std::is_integral_v<Src>) ||
33 (std::is_floating_point_v<Dst> && std::is_floating_point_v<Src>)) &&
34 (std::is_signed_v<Dst> ==
35 std::is_signed_v<Src>)&&(sizeof(Dst) >= sizeof(Src)))> {};
37 template <
typename Dst>
38 struct implicitly_within_limits<Dst, bool> : std::is_integral<Dst> {};
41 struct implicitly_within_limits<float, std::int16_t> : std::true_type {};
44 struct implicitly_within_limits<float, std::int32_t> : std::true_type {};
47 struct implicitly_within_limits<double, std::int16_t> : std::true_type {};
50 struct implicitly_within_limits<double, std::int32_t> : std::true_type {};
53 struct implicitly_within_limits<double, std::int64_t> : std::true_type {};
62 struct within_limits_num {
63 static constexpr
auto check(Src) noexcept {
64 return implicitly_within_limits<Dst, Src>::value;
68 template <
typename Dst,
typename Src,
bool IsInt,
bool IsSig>
69 struct within_limits_num<Dst, Src, IsInt, IsInt, IsSig, IsSig> {
70 static constexpr
auto check(Src value) noexcept {
71 using dnl = std::numeric_limits<Dst>;
73 return (dnl::min() <= value) && (value <= dnl::max());
77 template <
typename Dst,
typename Src,
bool IsInt>
78 struct within_limits_num<Dst, Src, IsInt, IsInt, false, true> {
79 static constexpr
auto check(Src value) noexcept {
80 using Dnl = std::numeric_limits<Dst>;
81 using Tmp = std::make_unsigned_t<Src>;
83 return (value < Src(0)) ? false : (Tmp(value) < Dnl::max());
87 template <
typename Dst,
typename Src,
bool IsInt>
88 struct within_limits_num<Dst, Src, IsInt, IsInt, true, false> {
89 static constexpr
auto check(Src value) noexcept {
90 using dnl = std::numeric_limits<Dst>;
92 return (value < dnl::max());
96 template <
typename Dst,
typename Src>
101 std::is_integral_v<Dst>,
102 std::is_integral_v<Src>,
103 std::is_signed_v<Dst>,
104 std::is_signed_v<Src>> {};
106 template <
typename T>
107 struct within_limits<T, T> {
108 static constexpr
auto check(T&) noexcept {
121 template <
typename Dst,
typename Src>
123 return implicitly_within_limits<Dst, Src>::value ||
124 within_limits<Dst, Src>::check(value);
132 template <
typename Dst,
typename Src>
134 -> std::enable_if_t<std::is_convertible_v<Src, Dst>, Dst> {
135 return EAGINE_CONSTEXPR_ASSERT(
136 is_within_limits<Dst>(value), Dst(std::move(value)));
143 template <
typename Dst,
typename Src>
147 if(is_within_limits<Dst>(value)) {
148 return {Dst(std::move(value)),
true};
157 #endif // EAGINE_IS_WITHIN_LIMITS_HPP