Round-Trip-Cast als Prüfung für verlustfreien Cast?
-
Ich hatte die Tage mal die Idee einen numerischen Cast nachzubasteln. Also fragte ich die KI. Was dabei herauskam war voller Fehler, lieferte aber einige wichtige Ideen.
Jedoch ist mir der folgende KI Code in Erinnerung geblieben.
#include <cassert> #include <cstdint> #include <type_traits> #include <limits> template <typename Target, typename Source> constexpr bool numeric_cast_valid(Target T, Source Value) { //... if constexpr (std::is_integral_v<Source> && std::is_floating_point_v<Target>) { if constexpr (std::numeric_limits<Target>::digits < std::numeric_limits<Source>::digits) { // Fragwürdiger Code Target CastedValue = static_cast<Target>(Value); if (static_cast<Source>(CastedValue) != Value) return false; } } return true; } int main() { float f = 0; int64_t v = 200; // Ziel // int8_t c1 = numeric_cast<int8_t>(v); // -> Fehler // uint8_t c2 = numeric_cast<uint8_t>(v); // -> OK assert(numeric_cast_valid(f, v)); return 0; }Darf man das so machen?
-
Von all den Zeilen ist Zeile 16 die fragwürdige? Das ist die, zu der ich die wenigsten bis gar keine Einwände hätte — im Kontrast zu all dem Rest. Was genau stört dich? Der Cast auf der rechten Seite ist ein gängiges Muster um Compilerwarnungen zu gefährlichen impliziten Umwandlungen zu unterdrücken (Im Vergleich zu
Target CastedValue = Value;), die man hier ja explizit durchführen und prüfen möchte.PS: Darf ich fragen, welches Modell das ausgespuckt hat? Das ist ja grauenhaft und erschreckend, wenn das 2026 produziert wurde.
-
Was genau stört dich?
Folgende Sachen finde ich etwas merkwürdig
- Die Unterstützung von Gleitkommazahlen und insbesonders
std::numeric_limits<Target>::digits < std::numeric_limits<Source>::digits)sowie die entsprechende Argumentation der KI. - Einen Cast erlauben zu wollen, wenn der cast Source -> Target -> Source das gleiche Ergebnis liefert. Ich vermute dass das Ganze nicht eindeutig ist. Ich schätze dass es z.B. zwei uint64_t Werte gibt, welche nach float gecastet den gleichen Wert in Binärdarstellung gibt.
Ich habe hierzu Copilot benutzt. Und in der letzten Zeit häufen sich meiner Meinung nach die schweren Fehler.
- Die Unterstützung von Gleitkommazahlen und insbesonders
-
Ich dachte, du meintest mit der Zeile 16 wäre speziell was falsch, weil du die hervorgehoben hattest. Die ist in Ordnung. Der ganze Rest ist gequirlter Unsinn, ja. Auf so vielen Ebenen Quatsch, dass ich dazu gar keine Kritik schreiben kann. Die Signatur ergibt ja noch nicht einmal Sinn; gescheitert im 0. Schritt.
-
@SeppJ sagte in Round-Trip-Cast als Prüfung für verlustfreien Cast?:
Auf so vielen Ebenen Quatsch,
Ok danke, das bestätigt meine Vermutungen.
-
Bezüglich der Grundidee, mir dem round trip: Das ist halt eine philosophische Frage, was du möchtest. Wenn A zu B wird und B zu A wird, ist dann nicht A äquivalent zu B? Das kann ich durchaus als mögliche Definition einer Gleichheit sehen
-
Ich habe das von Hand überarbeitet, und die ifs rausgeworfen, da diese als requires clause sinnvoller sind. Die ::digits Statements sind irgend wie sinnfrei, ich habe das so interpretiert, dass es keinen Wertverluste geben soll. Entspricht das nun eher Deinen Vorstellungen? Der Code aus der AI war eher Schrott, da er z.B. der Wertverlust bei der Konversion gar nicht abfängt.
#include <cstdlib> #include <cassert> #include <cstdint> #include <type_traits> #include <limits> template <typename Target, typename Source> requires ( std::is_integral_v<Source> && std::is_floating_point_v<Target> && (std::numeric_limits<Target>::digits10 >= std::numeric_limits<Source>::digits10) ) constexpr bool numeric_cast_valid(const Target T, const Source Value) { const decltype(T) CastedValue = static_cast<Target>(Value); const Source ValueRecasted = static_cast<Source>(CastedValue); if (Value == ValueRecasted) return true; return false; } int main() { float f = 0; int16_t v = 200; // Ziel // int8_t c1 = numeric_cast<int8_t>(v); // -> Fehler // uint8_t c2 = numeric_cast<uint8_t>(v); // -> OK assert(numeric_cast_valid(f, v)); return EXIT_SUCCESS; }