Skip to content

Commit 2b08bda

Browse files
refactor: Enhance floating-point literal handling with range checks and precision validation
Signed-off-by: FrozenlemonTee <1115306170@qq.com>
1 parent 3c9841d commit 2b08bda

1 file changed

Lines changed: 50 additions & 8 deletions

File tree

src/underlying/literals.cppm

Lines changed: 50 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,16 @@ consteval auto finite(T value) -> bool {
4545
value <= algorithms::max_value<T>();
4646
}
4747

48+
template <typename To, typename From>
49+
consteval auto out_of_floating_range(From value) -> bool {
50+
using value_type = std::remove_cv_t<To>;
51+
auto const normalized = static_cast<long double>(value);
52+
auto const lowest =
53+
static_cast<long double>(algorithms::lowest_value<value_type>());
54+
auto const max = static_cast<long double>(algorithms::max_value<value_type>());
55+
return normalized < lowest || normalized > max;
56+
}
57+
4858
template <std::integral To>
4959
consteval auto checked_integral_literal(unsigned long long value) -> To {
5060
using value_type = std::remove_cv_t<To>;
@@ -69,14 +79,12 @@ consteval auto checked_floating_literal(From value) -> To {
6979
}
7080
}
7181

72-
auto const normalized = static_cast<long double>(value);
73-
auto const lowest = static_cast<long double>(algorithms::lowest_value<value_type>());
74-
auto const max = static_cast<long double>(algorithms::max_value<value_type>());
75-
76-
if (normalized < lowest) {
77-
throw_literal_risk<conversion::risk::kind::underflow>();
78-
}
79-
if (normalized > max) {
82+
if (out_of_floating_range<value_type>(value)) {
83+
if constexpr (std::signed_integral<source_type> || std_floating<source_type>) {
84+
if (value < static_cast<source_type>(0)) {
85+
throw_literal_risk<conversion::risk::kind::underflow>();
86+
}
87+
}
8088
throw_literal_risk<conversion::risk::kind::overflow>();
8189
}
8290

@@ -93,6 +101,16 @@ consteval auto checked_floating_literal(From value) -> To {
93101
}
94102
}
95103

104+
return converted;
105+
}
106+
107+
template <std::floating_point To, std_numeric From>
108+
consteval auto exact_floating_literal(From value) -> To {
109+
using source_type = std::remove_cv_t<From>;
110+
using value_type = std::remove_cv_t<To>;
111+
112+
auto const converted = checked_floating_literal<value_type>(value);
113+
96114
if constexpr (std::integral<source_type>) {
97115
if (static_cast<source_type>(converted) != value) {
98116
throw_literal_risk<conversion::risk::kind::precision_loss>();
@@ -217,6 +235,14 @@ consteval auto operator""_f32(const long double value) -> float {
217235
return underlying::details::checked_floating_literal<float>(value);
218236
}
219237

238+
consteval auto operator""_f32e(const unsigned long long value) -> float {
239+
return underlying::details::exact_floating_literal<float>(value);
240+
}
241+
242+
consteval auto operator""_f32e(const long double value) -> float {
243+
return underlying::details::exact_floating_literal<float>(value);
244+
}
245+
220246
consteval auto operator""_f64(const unsigned long long value) -> double {
221247
return underlying::details::checked_floating_literal<double>(value);
222248
}
@@ -225,6 +251,14 @@ consteval auto operator""_f64(const long double value) -> double {
225251
return underlying::details::checked_floating_literal<double>(value);
226252
}
227253

254+
consteval auto operator""_f64e(const unsigned long long value) -> double {
255+
return underlying::details::exact_floating_literal<double>(value);
256+
}
257+
258+
consteval auto operator""_f64e(const long double value) -> double {
259+
return underlying::details::exact_floating_literal<double>(value);
260+
}
261+
228262
consteval auto operator""_f80(const unsigned long long value) -> long double {
229263
return underlying::details::checked_floating_literal<long double>(value);
230264
}
@@ -233,4 +267,12 @@ consteval auto operator""_f80(const long double value) -> long double {
233267
return underlying::details::checked_floating_literal<long double>(value);
234268
}
235269

270+
consteval auto operator""_f80e(const unsigned long long value) -> long double {
271+
return underlying::details::exact_floating_literal<long double>(value);
272+
}
273+
274+
consteval auto operator""_f80e(const long double value) -> long double {
275+
return underlying::details::exact_floating_literal<long double>(value);
276+
}
277+
236278
} // namespace mcpplibs::primitives::literals

0 commit comments

Comments
 (0)