|
13 | 13 | #pragma once |
14 | 14 |
|
15 | 15 | #include <type_traits> |
| 16 | +#include <cmath> |
16 | 17 | #include "simple_string.hpp" |
17 | 18 |
|
18 | 19 | #undef max |
@@ -88,9 +89,42 @@ inline void checkLowerLimit(const From& from) |
88 | 89 | template <typename From, typename To> |
89 | 90 | inline void checkTruncation(const From& from) |
90 | 91 | { |
91 | | - if(from != static_cast<From>(static_cast<To>(from))) |
| 92 | + // Handle integer to floating point |
| 93 | + if constexpr(std::is_integral_v<From> && std::is_floating_point_v<To>) |
92 | 94 | { |
93 | | - throw std::runtime_error("Floating point truncated"); |
| 95 | + // Check if value can be represented exactly in the target type |
| 96 | + constexpr auto max_exact = (1LL << std::numeric_limits<double>::digits) - 1; |
| 97 | + if(from > max_exact || from < -max_exact) |
| 98 | + { |
| 99 | + throw std::runtime_error("Loss of precision when converting a large integer number " |
| 100 | + "to floating point:" + |
| 101 | + std::to_string(from)); |
| 102 | + } |
| 103 | + } |
| 104 | + // Handle floating point to integer |
| 105 | + else if constexpr(std::is_floating_point_v<From> && std::is_integral_v<To>) |
| 106 | + { |
| 107 | + if(from > static_cast<From>(std::numeric_limits<To>::max()) || |
| 108 | + from < static_cast<From>(std::numeric_limits<To>::lowest()) || |
| 109 | + from != std::nearbyint(from)) |
| 110 | + { |
| 111 | + throw std::runtime_error("Invalid floating point to integer conversion"); |
| 112 | + } |
| 113 | + } |
| 114 | + // Handle other conversions |
| 115 | + else |
| 116 | + { |
| 117 | + if(from > static_cast<From>(std::numeric_limits<To>::max()) || |
| 118 | + from < static_cast<From>(std::numeric_limits<To>::lowest())) |
| 119 | + { |
| 120 | + throw std::runtime_error("Value outside numeric limits"); |
| 121 | + } |
| 122 | + To as_target = static_cast<To>(from); |
| 123 | + From back_to_source = static_cast<From>(as_target); |
| 124 | + if(from != back_to_source) |
| 125 | + { |
| 126 | + throw std::runtime_error("Value truncated in conversion"); |
| 127 | + } |
94 | 128 | } |
95 | 129 | } |
96 | 130 |
|
|
0 commit comments