mirror of
https://github.com/boostorg/numeric_conversion.git
synced 2026-01-26 06:42:23 +00:00
127 lines
4.0 KiB
Plaintext
127 lines
4.0 KiB
Plaintext
[/
|
|
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 numeric_conversion_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]
|
|
|
|
[#numeric_conversion_numeric_cast]
|
|
|
|
[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]
|