quant
quant

Reputation: 23082

How can I check whether a cast will result in overflow or underflow of the target type?

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

Answers (1)

Sean Cline
Sean Cline

Reputation: 7199

Unfortunately, no such function exists in the C++ standard library. That leaves a few options:


Option #1: 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.


Option #2: 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.


Option #3: Roll your own.

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

Related Questions