Ich möchte überprüfen, ob eine bestimmte Double/Float-Variable das aktuelle Bitmuster 0x0 hat. Fragen Sie nicht warum, es wird in einer Funktion in Qt verwendet ( qIsNull()
), die ich gerne sein möchte constexpr
.
Der ursprüngliche Code verwendete eine Vereinigung:
union { double d; int64_t i; } u;
u.d = d;
return u.i == 0;
Das funktioniert nicht als constexpr
natürlich.
Der nächste Versuch war mit reinterpret_cast
:
return *reinterpret_cast<int64_t*>(&d) == 0;
Das funktioniert zwar als constexpr
in GCC 4.7, es scheitert (zu Recht, b/c von Zeigermanipulation) in Clang 3.1.
Die letzte Idee war, dies auf alexandrinische Art und Weise zu tun:
template <typename T1, typename T2>
union Converter {
T1 t1;
T2 t2;
explicit constexpr Converter( T1 t1 ) : t1(t1) {}
constexpr operator T2() const { return t2; }
};
// in qIsNull():
return Converter<double,int64_t>(d);
Aber auch das ist für Clang nicht clever genug:
note: read of member 't2' of union with active member 't1' is not allowed in a constant expression
constexpr operator T2() const { return t2; }
^
Hat sonst noch jemand eine gute Idee?
1 Stimmen
Ich vermute, es gibt noch andere Bitmuster, die ebenfalls eine Fließkomma-0 darstellen, die Sie nicht finden wollen?
2 Stimmen
Es gibt genau zwei Bitmuster, die 0 darstellen, nämlich 000...000 und 100...000. Das erste Bit ist das Vorzeichenbit. Das zweite Bitmuster wird manchmal auch als "negative Null" bezeichnet.
2 Stimmen
Vielleicht
return d == 0 && 1/d > 0;
? ( de.wikipedia.org/wiki/Signed_zero#Vergleiche )1 Stimmen
Don't ask why
Sagen Sie mir nicht, was ich tun soll3 Stimmen
@Lightness: Sag Marc nicht, was er nicht tun soll ;-p
0 Stimmen
reinterpret_cast
darf nicht in konstanten Ausdrücken vorkommen. Was aber, wenn Sie versuchenstatic_cast<const int64_t*>(static_cast<const void*>(&d))
stattdessen?1 Stimmen
@LucDanton: Ich glaube nicht, dass es eine
reinterpret_cast
vs.static_cast
das ist das Problem, zumindest lehnt Clang beides ab. Ich schätze, es mag es nicht, die Adresse zu nehmen. Denn wie könnte es das zur Kompilierzeit berechnen?0 Stimmen
@jdv-JandeVaan: vgl. den ursprünglichen Code. Er testet auf ein wörtliches 0x0-Bitmuster, nicht auf FP-gleich-Null. Ich frage mich, warum sie so scharf darauf sind, -0 zu überspringen, aber in erster Näherung möchte ich die Verhaltenskompatibilität beibehalten, während ich das Ding umdrehe
constexpr
...0 Stimmen
@MarcMutz-mmutz Addressof ist als konstanter Ausdruck in Ordnung. Er erscheint sogar in den (nicht-normativen) Beispielen:
constexpr const int* addr(const int& ir) { return &ir; } // OK
.reinterpret_cast
andererseits ist ausdrücklich Verboten. Das wird natürlich ein Hindernis sein.