In C++, is there a compile-time way to compute the largest value of an integral type T
that can be safely squared, i.e. that mathematically x * x <= std::numeric_limits<T>::max()
so that if the operation x*x
were to be performed, it would not cause undefined behavior (for signed types) or overflow (for unsigned types?
I'm fine restricting to only integral types that have specializations in std::numeric_limits
, i.e. no need to worry about new user-defined integral types, if that makes it any easier.
Mathematically, of course, the answer is floor(sqrt(std::numeric_limits<T>::max()))
.
For example, this would be floor(sqrt(2^63-1)) == 3037000499
for a 64-bit signed long long. A (correct even for large numbers) constexpr sqrt would do the trick, though I don't know if that is the best way.
Answers should be:
- 64-bit unsigned:
floor(sqrt(2^64-1)) == 4294967295
- 64-bit signed:
floor(sqrt(2^63-1)) == 3037000499
- 32-bit unsigned:
floor(sqrt(2^32-1)) == 65535
- 32-bit signed:
floor(sqrt(2^31-1)) == 46340