@@ -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+
4858template <std::integral To>
4959consteval 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+
220246consteval 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+
228262consteval 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