123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293 |
- [/
- 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]
|