I want to check that a given double/float variable has the actual bit pattern 0x0. Don't ask why, it's used in a function in Qt (qIsNull()
) that I'd like to be constexpr
.
The original code used a union:
union { double d; int64_t i; } u;
u.d = d;
return u.i == 0;
This doesn't work as a constexpr
of course.
The next try was with reinterpret_cast
:
return *reinterpret_cast<int64_t*>(&d) == 0;
But while that works as a constexpr
in GCC 4.7, it fails (rightfully, b/c of pointer manipulation) in Clang 3.1.
The final idea was to go Alexandrescuesque and do this:
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);
But that's not clever enough for Clang, either:
note: read of member 't2' of union with active member 't1' is not allowed in a constant expression
constexpr operator T2() const { return t2; }
^
Does anyone else have a good idea?
return d == 0 && 1/d > 0;
? (en.wikipedia.org/wiki/Signed_zero#Comparisons) – PressmanDon't ask why
Don't tell me what to do – Lahdidahreinterpret_cast
is prohibited to appear in constant expressions. But what if you attemptstatic_cast<const int64_t*>(static_cast<const void*>(&d))
instead? – Strontianitereinterpret_cast
vs.static_cast
that's the issue, at least Clang rejects both. I guess it doesn't like taking the address. After all, how could it compute that at compile-time? – Esquedaconstexpr
... – Esquedaconstexpr const int* addr(const int& ir) { return &ir; } // OK
.reinterpret_cast
, on the other hand, is explicitly forbidden. So obviously that's going to be a roadblock. – Strontianite