Ich möchte überprüfen, ob eine gegebene double / float-Variable das tatsächliche Bitmuster 0x0 hat. Frag nicht warum, es wird in einer Funktion in Qt ( qIsNull()
) verwendet, die ich gerne constexpr
wäre.
Der ursprüngliche Code verwendete eine Union:
%Vor% Dies funktioniert natürlich nicht als constexpr
.
Der nächste Versuch war mit reinterpret_cast
:
Aber während dies in GCC 4.7 als constexpr
funktioniert, scheitert es (zu Recht, b / c der Zeigermanipulation) in Clang 3.1.
Die letzte Idee war, Alexandrescuesque zu gehen und dies zu tun:
%Vor%Aber das ist auch nicht clever genug für Clang:
%Vor%Hat jemand anderes eine gute Idee?
Ich möchte überprüfen, ob eine gegebene double / float Variable das tatsächliche Bitmuster 0x0
hat
Aber wenn es constexpr
ist, dann prüft es keine Variable , es prüft den Wert , für den diese Variable statisch bestimmt ist. Deshalb sollten Sie keine Pointer- und Union-Tricks machen, "offiziell" gibt es keinen Speicher, auf den Sie zeigen können.
Wenn Sie Ihre Implementierung davon überzeugen können, IEEE-Division-by-Zero nicht einzufangen, können Sie etwas tun wie:
%Vor% Nur +/-0
sind gleich 0. 1/-0
ist -Inf
, was nicht größer als 0 ist. 1/+0
ist +Inf
, was ist. Aber ich weiß nicht, wie man diese Nicht-Überfüllungsarithmetik passieren lässt.
Es ist nicht möglich, das zugrunde liegende Bitmuster eines double
innerhalb eines konstanten Ausdrucks zu betrachten. Es gab einen Fehler im C ++ 11-Standard, der eine solche Überprüfung durch Casting über void*
zuließ, aber das wurde von C ++ - Kernproblem 1312 .
Als "Beweis" hat die constexpr
-Implementierung von clang (die als vollständig angesehen wird) keinen Mechanismus zum Extrahieren der Repräsentation eines konstanten double
-Werts (anders als über Nicht-Standard-Vektoroperationen, und selbst dann gibt es) derzeit keine Möglichkeit, das Ergebnis zu überprüfen).
Wie andere vorgeschlagen haben, wenn Sie wissen, dass Sie auf eine Plattform abzielen, die IEEE-754 Fließkommawerte verwendet, entspricht 0x0
dem Wert positive Null. Ich glaube, der einzige Weg dies zu erkennen, der in einem konstanten Ausdruck sowohl in clang als auch in g ++ funktioniert, ist __builtin_copysign
:
Tags und Links c++ c++11 floating-point constexpr casting