a05ae1dc97
[SVN r51417]
294 lines
10 KiB
Plaintext
294 lines
10 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 converter<> function object]
|
|
|
|
[section Synopsis]
|
|
|
|
namespace boost { namespace numeric {
|
|
|
|
|
|
template<class T,
|
|
class S,
|
|
class Traits, = conversion_traits<T,S>
|
|
class OverflowHandler = def_overflow_handler,
|
|
class Float2IntRounder = Trunc< typename Traits::source_type >,
|
|
class RawConverter = raw_converter<Traits>,
|
|
class UserRangeChecker = UseInternalRangeChecker
|
|
>
|
|
struct converter
|
|
{
|
|
typedef Traits traits ;
|
|
|
|
typedef typename Traits::source_type source_type ;
|
|
typedef typename Traits::argument_type argument_type ;
|
|
typedef typename Traits::result_type result_type ;
|
|
|
|
static result_type convert ( argument_type s ) ;
|
|
|
|
result_type operator() ( argument_type s ) const ;
|
|
|
|
// Internal member functions:
|
|
|
|
static range_check_result out_of_range ( argument_type s ) ;
|
|
static void validate_range ( argument_type s ) ;
|
|
static result_type low_level_convert ( argument_type s ) ;
|
|
static source_type nearbyint ( argument_type s ) ;
|
|
|
|
} ;
|
|
|
|
} } // namespace numeric, boost
|
|
|
|
|
|
`boost::numeric::converter<>` is a __SGI_UNARY_FUNCTION__ encapsulating
|
|
the code to perform a numeric conversion with the direction and
|
|
properties specified by the Traits template parameter. It can optionally
|
|
take some [link boost_numericconversion.numeric_converter_policy_classes policies] which can be used to customize its behavior. The
|
|
`Traits` parameter is not a policy but the parameter that defines
|
|
the conversion.
|
|
|
|
[endsect]
|
|
|
|
[section Template parameters]
|
|
|
|
[table
|
|
[[ ][ ]]
|
|
[[`T`][
|
|
The [link boost_numericconversion.definitions.numeric_types Numeric Type]
|
|
which is the ['Target] of the conversion.
|
|
]]
|
|
[[`S`][
|
|
The [link boost_numericconversion.definitions.numeric_types Numeric Type]
|
|
which is the ['Source] of the conversion.
|
|
]]
|
|
[[`Traits`][
|
|
This must be a conversion traits class with the interface of
|
|
[link boost_numericconversion.conversion_traits___traits_class `boost::numeric::conversion_traits`]
|
|
]]
|
|
[[`OverflowHandler`][
|
|
[*Stateless Policy] called to administrate the result of the range checking.
|
|
|
|
It is a [*Function Object] which receives the result of `out_of_range()`
|
|
and is called inside the `validate_range()` static member function exposed
|
|
by the converter.
|
|
]]
|
|
[[`Float2IntRounder`][
|
|
[*Stateless Policy] which specifies the rounding mode used for float to
|
|
integral conversions.
|
|
|
|
It supplies the `nearbyint()` static member function exposed by the converter.
|
|
]]
|
|
[[`RawConverter`][
|
|
[*Stateless Policy] which is used to perform the actual conversion.
|
|
|
|
It supplies the `low_level_convert()` static member function exposed
|
|
by the converter.
|
|
]]
|
|
[[`UserRangeChecker`][
|
|
['Special and Optional] [*Stateless Policy] which can be used to override
|
|
the internal range checking logic.
|
|
|
|
If given, supplies alternative code for the `out_of_range()` and
|
|
`validate_range()` static member functions exposed by the converter.
|
|
]]
|
|
]
|
|
|
|
[endsect]
|
|
|
|
[section Member functions]
|
|
|
|
[: `static result_type converter<>::convert ( argument_type s ) ; // throw
|
|
`]
|
|
|
|
This static member function converts an rvalue of type `source_type` to
|
|
an rvalue of type `target_type`.
|
|
|
|
If the conversion requires it, it performs a range checking before the conversion
|
|
and passes the result of the check to the overflow handler policy (the default
|
|
policy throws an exception if out-of-range is detected)
|
|
|
|
The implementation of this function is actually built from the policies and is
|
|
basically as follows:
|
|
|
|
result_type converter<>::convert ( argument_type s )
|
|
{
|
|
validate_range(s); // Implemented by the internal range checking logic
|
|
// (which also calls the OverflowHandler policy)
|
|
// or externally supplied by the UserRangeChecker policy.
|
|
|
|
s = nearbyint(s); // Externally supplied by the Float2IntRounder policy.
|
|
// NOTE: This is actually called only for float to int conversions.
|
|
|
|
return low_level_convert(s); // Externally supplied by the RawConverter policy.
|
|
}
|
|
|
|
`converter<>::operator() const` just calls `convert()`
|
|
|
|
__SPACE__
|
|
|
|
[: `static range_check_result numeric_converter<>::out_of_range ( argument_type s ) ;`]
|
|
|
|
This [link numeric_conversion_converter_internal internal] static member function
|
|
determines if the value `s` can be
|
|
represented by the target type without overflow.
|
|
|
|
It does not determine if the conversion is ['exact]; that is, it does not detect
|
|
['inexact] conversions, only ['out-of-range] conversions (see the
|
|
[link boost_numericconversion.definitions.exact__correctly_rounded_and_out_of_range_representations Definitions] for further details).
|
|
|
|
The return value is of enum type
|
|
[link boost_numericconversion.numeric_converter_policy_classes.enum_range_check_result `boost::numeric::range_check_result`]
|
|
|
|
The actual code for the range checking logic is optimized for the combined
|
|
properties of the source and target types. For example, a non-subranged
|
|
conversion (i.e: `int`->`float`), requires no range checking, so `out_of_range()`
|
|
returns `cInRange` directly. See the following
|
|
[link boost_numericconversion.converter___function_object.range_checking_logic table] for more details.
|
|
|
|
If the user supplied a
|
|
[link boost_numericconversion.numeric_converter_policy_classes.policy_userrangechecker UserRangeChecker] policy,
|
|
is this policy which implements this function, so the implementation is user
|
|
defined, although it is expected to perform the same conceptual check and
|
|
return the appropriate result.
|
|
|
|
__SPACE__
|
|
|
|
[: `static void numeric_converter<>::validate_range ( argument_type s ) ; // no throw
|
|
`]
|
|
|
|
This [link numeric_conversion_converter_internal internal] static member function
|
|
calls out_of_range(s), and passes the
|
|
result to the [link boost_numericconversion.numeric_converter_policy_classes.policy_overflowhandler OverflowHandler]
|
|
policy class.
|
|
|
|
For those Target/Source combinations which don't require range checking, this
|
|
is an empty inline function.
|
|
|
|
If the user supplied a
|
|
[link boost_numericconversion.numeric_converter_policy_classes.policy_userrangechecker UserRangeChecker] policy,
|
|
is this policy which implements this function, so the implementation is user
|
|
defined, although it is expected to perform the same action as the default.
|
|
In particular, it is expected to pass the result of the check to the overflow handler.
|
|
|
|
__SPACE__
|
|
|
|
[: `static result_type numeric_converter<>::low_level_convert ( argument_type s ) ;` ]
|
|
|
|
This [link numeric_conversion_converter_internal internal] static member function
|
|
performs the actual conversion.
|
|
|
|
This function is externally supplied by the
|
|
[link boost_numericconversion.numeric_converter_policy_classes.policy_rawconverter RawConverter] policy class.
|
|
|
|
__SPACE__
|
|
|
|
[: `static source_type converter<>::nearbyint ( argument_type s ) ;`]
|
|
|
|
This [link numeric_conversion_converter_internal internal] static member function,
|
|
which is [_only used] for
|
|
`float` to `int` conversions, returns an ['integer] value of ['[_floating-point
|
|
type]] according to some rounding direction.
|
|
|
|
This function is externally supplied by the
|
|
[link boost_numericconversion.numeric_converter_policy_classes.policy_float2introunder Float2IntRounder] policy class
|
|
which encapsulates the specific rounding mode.
|
|
|
|
__SPACE__
|
|
|
|
[#numeric_conversion_converter_internal]
|
|
|
|
[heading Internal Member Functions]
|
|
|
|
These static member functions build the actual conversion code used by `convert()`.
|
|
The user does not have to call these if calling `convert()`, since `convert()` calls
|
|
them infernally, but they can be called separately for specific needs.
|
|
|
|
[endsect]
|
|
|
|
[section Range Checking Logic]
|
|
|
|
The following table summarizes the internal range checking logic performed for
|
|
each combination of the properties of Source and Target.
|
|
|
|
LowestT/HighestT denotes the highest and lowest values of the Target type, respectively.
|
|
|
|
`S(n)` is short for `static_cast<S>(n)` (`S` denotes the Source type).
|
|
|
|
`NONE` indicates that for this case there is no range checking.
|
|
|
|
[pre
|
|
[^
|
|
int_to_int |--> sig_to_sig |--> subranged |--> ( s >= S(LowestT) ) && ( s <= S(HighestT) )
|
|
| |--> not subranged |--> NONE
|
|
|
|
|
|--> unsig_to_unsig |--> subranged |--> ( s >= S(LowestT) ) && ( s <= S(HighestT) )
|
|
| |--> not subranged |--> NONE
|
|
|
|
|
|--> sig_to_unsig |--> pos subranged |--> ( s >= S(0) ) && ( s <= S(HighestT) )
|
|
| |--> not pos subranged |--> ( s >= S(0) )
|
|
|
|
|
|--> unsig_to_sig |--> subranged |--> ( s <= S(HighestT) )
|
|
| |--> not subranged |--> NONE
|
|
]
|
|
[^
|
|
int_to_float |--> NONE
|
|
]
|
|
[^
|
|
float_to_int |--> round_to_zero |--> ( s > S(LowestT)-S(1) ) && ( s < S(HighestT)+S(1) )
|
|
|--> round_to_even_nearest |--> ( s >= S(LowestT)-S(0.5) ) && ( s < S(HighestT)+S(0.5) )
|
|
|--> round_to_infinity |--> ( s > S(LowestT)-S(1) ) && ( s <= S(HighestT) )
|
|
|--> round_to_neg_infinity |--> ( s >= S(LowestT) ) && ( s < S(HighestT)+S(1) )
|
|
]
|
|
[^
|
|
float_to_float |--> subranged |--> ( s >= S(LowestT) ) && ( s <= S(HighestT) )
|
|
|--> not subranged |--> NONE
|
|
]
|
|
]
|
|
|
|
|
|
|
|
[endsect]
|
|
|
|
[section Examples]
|
|
|
|
#include <cassert>
|
|
#include <boost/numeric/conversion/converter.hpp>
|
|
|
|
int main() {
|
|
|
|
typedef boost::numeric::converter<int,double> Double2Int ;
|
|
|
|
int x = Double2Int::convert(2.0);
|
|
assert ( x == 2 );
|
|
|
|
int y = Double2Int()(3.14); // As a function object.
|
|
assert ( y == 3 ) ; // The default rounding is trunc.
|
|
|
|
try
|
|
{
|
|
double m = boost::numeric::bounds<double>::highest();
|
|
int z = Double2Int::convert(m); // By default throws positive_overflow()
|
|
}
|
|
catch ( boost::numeric::positive_overflow const& )
|
|
{
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
[endsect]
|
|
|
|
[endsect]
|
|
|
|
|
|
|
|
|
|
|