Alex Rivera | Logout

How to check a double's bit pattern is 0x0 in a C++11 constexpr?

Asked 2012-02-17T12:31:03.943
9

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?

Edit
Report

2 Answers

6

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

But if it's constexpr then it's not checking any variable, it's checking the value that this variable is statically determined to hold. That's why you aren't supposed to pull pointer and union tricks, "officially" there isn't any memory to point at.

If you can persuade your implementation to do non-trapping IEEE division-by-zero, then you could do something like:

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

Only +/-0 are equal to 0. 1/-0 is -Inf, which isn't greater than 0. 1/+0 is +Inf, which is. But I don't know how to make that non-trapping arithmetic happen.

answered 2012-02-17T13:49:08.990
5

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

return x == 0 && std::signbit(x) == 0;
answered 2012-02-17T13:54:31.500

Your Answer