Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Using boost::numeric_cast<>

When I want to convert between different integer types, it seems the best syntax is to use boost::numeric_cast<>():

int y = 99999;
short x = boost::numeric_cast<short>(y); // will throw an exception if y is too large

I have never used that; however the syntax is pretty straightforward, so all is well.

Now suppose I want to do something a bit more advanced: instead of throwing an exception, I'd like it to return the min or max of the target type (saturation). I couldn't figure out a way to express that, but the documentation suggests that it is possible (probably using RawConverter policy). All I could come up with is the following ugly:

short x = numeric_cast<short>(max(min(y, SHORT_MAX), SHORT_MIN);

So how can I express "saturating cast" using boost's numeric_cast?

like image 632
anatolyg Avatar asked Dec 12 '10 21:12

anatolyg


1 Answers

You could probably do something like this:

#include <limits>

template<typename Target, typename Source>
Target saturation_cast(Source src) {
   try {
      return boost::numeric_cast<Target>(src);
   }
   catch (const boost::negative_overflow &e) {
      return std::numeric_limits<Target>::lowest();
      /* Or, before C++11:
      if (std::numeric_limits<Target>::is_integer)
         return std::numeric_limits<Target>::min();
      else
         return -std::numeric_limits<Target>::max();
      */
   }
   catch (const boost::positive_overflow &e) {
      return std::numeric_limits<Target>::max();
   }
}

(For types that support it the error cases could also return -inf/+inf).

This way you let Boost's numeric_cast determine if the value is out of bounds and can then react accordingly.

like image 92
sth Avatar answered Oct 13 '22 21:10

sth