How to check double bit pattern 0x0 in C ++ 11 constexpr?

I want to check that the given double / float variable has the actual bit pattern 0x0. Don't ask why, he used in the Qt ( qIsNull() ) function that I would like to be constexpr .

The source code uses the union:

 union { double d; int64_t i; } u; ud = d; return ui == 0; 

It does not work like constexpr , of course.

The following attempt was with reinterpret_cast :

 return *reinterpret_cast<int64_t*>(&d) == 0; 

But while this works like constexpr in GCC 4.7, it fails (by right, b / c 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 this is not too smart for the Clan, 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?

+8
c ++ floating-point casting c ++ 11 constexpr
source share
3 answers

I want to check that the given double / float variable has the actual bit pattern 0x0

But if it is constexpr , then it does not check any variable, checking the value that this variable is statically defined for storage. That is why you should not pull out the signs and tricks of the allies, "officially" there is no point of memory.

If you can convince your implementation that I am not dividing IEEE division by zero, you can do something like:

 return (d == 0) && (1 / d > 0) 

Only +/-0 are 0. 1/-0 is -Inf , which is not more than 0. 1/+0 is +Inf , which is. But I do not know how to do this arithmetic, not related to the trap.

+6
source share

It seems like clang ++ 3.0 and g ++ 4.7 (but not 4.6) treat std::signbit as constexpr .

 return x == 0 && std::signbit(x) == 0; 
+5
source share

Unable to view base double bit pattern from constant expression. There was a defect in the C ++ 11 standard, which allowed such verification by casting via void* , but this was addressed to the C32 1312 kernel problem .

As a "proof", the implementation of clang constexpr (which is considered complete) has no mechanism for extracting the representation of the value of the constant double (except through non-standard vector operations, and even then there is currently no way to verify the result).

As suggested by others, if you know you will be targeting an IEEE-754 floating point platform, 0x0 corresponds to a positive zero value. I believe the only way to detect this, which works inside a constant expression in both clang and g ++, is to use __builtin_copysign :

 constexpr bool isPosZero(double d) { return d == 0.0 && __builtin_copysign(1.0, d) == 1.0; } 
+4
source share

All Articles