Somebody's going to come by and point out this is all-wrong standards-wise.
Anyway, decimal machines aren't allowed anymore and through the ages there's been only one negative zero. As a practical matter, these tests suffice:
INT_MIN == -INT_MAX && ~0 == 0
but your code doesn't work for two reasons. Despite what the standard says, constexprs are evaluated on the host using host rules, and there exists an architecture where this crashes at compile time.
Trying to massage out the trap is not possible. ~(unsigned)0 == (unsigned)-1
reliably tests for 2s compliment, so it's inverse does indeed check for one's compliment*; however, ~0
is the only way to generate negative zero on ones compliment, and any use of that value as a signed number can trap so we can't test for its behavior. Even using platform specific code, we can't catch traps in constexpr, so forgetaboutit.
*barring truly exotic arithmetic but hey
Everybody uses #define
s for architecture selection. If you need to know, use it.
If you handed me an actually standards complaint compiler that yielded a compile error on trap in a constexpr and evaluated with target platform rules rather than host platform rules with converted results, we could do this:
target.o: target.c++
$(CXX) -c target.c++ || $(CC) -DTRAP_ZERO -c target.c++
bool has_negativezero() {
#ifndef -DTRAP_ZERO
return INT_MIN == -INT_MAX && ~0 == 0;
#else
return 0;
#endif
}
gets
in ISO C). – Pretended-std::numeric_limits<T>::max()==std::numeric_limits<T>::lowest()
could work. – Mesomorphic