123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153 |
- [/
- 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.
- By default `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
- Target numeric_cast( Source arg )
- {
- typedef conversion_traits<Target, Source> conv_traits;
- typedef numeric_cast_traits<Target, Source> cast_traits;
- typedef converter
- <
- Target,
- Source,
- conv_traits,
- typename cast_traits::overflow_policy,
- typename cast_traits::rounding_policy,
- raw_converter<conv_traits>,
- typename cast_traits::range_checking_policy
- > converter;
- return converter::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 overflow policy
- is executed whose default behavior is to throw an an exception (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 numeric_cast_traits]
- template <typename Target, typename Source, typename EnableIf = void>
- struct numeric_cast_traits
- {
- typedef def_overflow_handler overflow_policy;
- typedef UseInternalRangeChecker range_checking_policy;
- typedef Trunc<Source> rounding_policy;
- };
- The behavior of `numeric_cast` may be tailored for custom numeric types through
- the specialization of `numeric_cast_traits`. (see
- [link boost_numericconversion.type_requirements_and_user_defined_types_support User Defined Types]
- for details.
- )
- [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]
|