| [/ |
| Boost.Optional |
| |
| Copyright (c) 2003-2007 Fernando Luis Cacciola Carballal |
| |
| Distributed under the Boost Software License, Version 1.0. |
| (See accompanying file LICENSE_1_0.txt or copy at |
| http://www.boost.org/LICENSE_1_0.txt) |
| ] |
| |
| [section Improved numeric_cast<>] |
| |
| [section Introduction] |
| |
| The lack of preservation of range makes conversions between numeric types |
| error prone. This is true for both implicit conversions and explicit |
| conversions (through `static_cast`). |
| [link boost_numericconversion.improved_numeric_cast__.numeric_cast `numeric_cast`] |
| detects loss of range when a numeric type is converted, and throws an |
| exception if the range cannot be preserved. |
| |
| There are several situations where conversions are unsafe: |
| |
| * Conversions from an integral type with a wider range than the target integral type. |
| * Conversions from unsigned to signed (and vice versa) integral types. |
| * Conversions from floating point types to integral types. |
| |
| 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. |
| |
| `numeric_cast` adheres to the rules for implicit conversions mandated by |
| the C++ Standard, such as truncating floating point types when converting |
| to integral types. The implementation must guarantee that for a conversion |
| to a type that can hold all possible values of the source type, there will |
| be no runtime overhead. |
| |
| [endsect] |
| |
| [section numeric_cast] |
| |
| 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); |
| } |
| |
| `numeric_cast` returns the result of converting a value of type Source |
| to a value of type Target. If out-of-range is detected, an exception is |
| thrown (see |
| [link numeric_conversion_bad_numeric_cast bad_numeric_cast], |
| [link numeric_conversion_negative_overflow negative_overflow] and |
| [link numeric_conversion_possitive_overflow positive_overflow] |
| ). |
| |
| [endsect] |
| |
| [section Examples] |
| |
| The following example performs some typical conversions between numeric types: |
| |
| #include <boost/numeric/conversion/cast.hpp> |
| #include <iostream> |
| |
| 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; |
| } |
| |
| [endsect] |
| |
| [endsect] |