Is there a function in the Standard Library / Boost that will check whether a cast will result in overflow/underflow of the target type? For example:
unsigned value = static_cast<unsigned>(12.3); // this should pass (lossy but no overflow)
unsigned value = static_cast<unsigned>(1E123); // this should fail
unsigned value = static_cast<unsigned>(-2); // this should also fail
Does somethign like this exist? For the above examples the feature might have functionality similar to this:
template <typename Source, typename Target>
bool checkNoOverflow(const Source value)
{
return value >= std::numeric_limits<Target>::lowest() && value <= std::numeric_limits<Target>::max();
}
The above is just a simplified example, which would fail on corner-cases such as this:
unsigned value = static_cast<unsigned>(-0.1); // valid, result is 0
To be clear, I'm not asking about how to write a function that would work for all cases, but rather I'm after existing functionality in the Standard Library or boost that does this for me.
Unfortunately, no such function exists in the C++ standard library. That leaves a few options:
boost::numeric_cast
If you have access to Boost, then boost::numeric_cast
should do exactly what you want. It will perform a conversion between two numeric types unless the conversion would go outside the range of the target type. In such cases, a boost::numeric::bad_numeric_cast
exception is thrown.
gsl::narrow()
Alternatively, gsl::narrow
is a good option. I'd consider it preferable to Boost if you are OK with bringing GSL into your project.
If you were curious about implementing your own conversion, you can take a look at The C++ Programming Language 4th Edition by Bjarne Stroustrup (ISBN 978-0321563842).
In Chapter 11.5, he defines a narrow_cast
as such:
template<class Target, class Source>
Target narrow_cast(Source v)
{
auto r = static_cast<Target>(v); // convert the value to the target type
if (static_cast<Source>(r)!=v)
throw runtime_error("narrow_cast<>() failed");
return r;
}
This implementation is quite bare and doesn't go quite as far as Boost's does, but could conceivably be modified to suit your needs.