The lack of preservation of range makes conversions between numeric types
error prone. This is true for both implicit conversions and explicit conversions
(through There are several situations where conversions are unsafe:
The C++ Standard does not specify the behavior when a numeric type is assigned a value that cannot be represented by the type, except for unsigned integral types [3.9.1.4], which must obey the laws of arithmetic modulo 2n (this implies that the result will be reduced modulo the number that is one greater than the largest value that can be represented). The fact that the behavior for overflow is undefined for all conversions (except the aforementioned unsigned to unsigned) makes any code that may produce positive or negative overflows exposed to portability issues.
template<typename Target, typename Source> inline typename boost::numeric::converter<Target,Source>::result_type numeric_cast ( Source arg ) { return boost::numeric::converter<Target,Source>::convert(arg); }
The following example performs some typical conversions between numeric types:
int main() { using boost::numeric_cast; using boost::numeric::bad_numeric_cast; using boost::numeric::positive_overflow; using boost::numeric::negative_overflow; try { int i=42; short s=numeric_cast<short>(i); // This conversion succeeds (is in range) } catch(negative_overflow& e) { std::cout << e.what(); } catch(positive_overflow& e) { std::cout << e.what(); } try { float f=-42.1234; // This will cause a boost::numeric::negative_overflow exception to be thrown unsigned int i=numeric_cast<unsigned int>(f); } catch(bad_numeric_cast& e) { std::cout << e.what(); } double d= f + numeric_cast<double>(123); // int -> double unsigned long l=std::numeric_limits<unsigned long>::max(); try { // This will cause a boost::numeric::positive_overflow exception to be thrown // NOTE: *operations* on unsigned integral types cannot cause overflow // but *conversions* to a signed type ARE range checked by numeric_cast. unsigned char c=numeric_cast<unsigned char>(l); } catch(positive_overflow& e) { std::cout << e.what(); } return 0; } |