*
@SeppJ sagte in Round-Trip-Cast als Prüfung für verlustfreien Cast?:
Ich würde digits und so komplett ignorieren. Die Eigenschaften des Typs haben ja überhaupt keine Bedeutung für Wertverluste.
Natürlich kann es zu Wertverlusten kommen, wenn der Typ zu klein ist. Das Problem ist, dass Du ohne große Verrenkungen nicht in der Lage bist den Wertebereich zum Übersetzungszeitpunkt zu checken.
emplate <typename Target, typename Source>
requires(
std::is_integral_v<Source> &&
std::is_floating_point_v<Target>
)
constexpr Target numeric_cast(const Source Value) {
constexpr __int128_t one = 1;
constexpr __int128_t digits = std::numeric_limits<Target>::digits;
constexpr __int128_t max_size = one << digits;
if (Value > max_size) throw std::runtime_error("Value does not fit into Target");
return static_cast<Target>(Value);
}
numeric_cast enthält dann eine if-Abfrage, die man leider nicht constexpr machen kann, da es bisher keine constexpr Parameter für Funktionen gibt. Man kann natürlich eine Template mit einem Zahlenparameter bauen, der dann in der Lage ist, den Wertebereich zu prüfen.
P.S. Die 128Bit des Integer Typens ist notwendig, weil long double bei vielen Compiler als Quad Precision interpretiert wird.
Die Zahl 0.1 aus einem Dezimaltyp mit nur einer Nachkommastelle kann hingegen niemals exakt in einen binären Fließkommatyp umgewandelt werden, egal wie exakt der ist.
Da hier die Funktion immer von Integer zu Floating Point konvertiert, gibt es das Problem nicht.