Reputation: 23082
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.
Upvotes: 6
Views: 2509
Reputation: 7199
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.
Upvotes: 9