]>
Commit | Line | Data |
---|---|---|
7c673cae FG |
1 | [/ |
2 | Boost.Optional | |
3 | ||
4 | Copyright (c) 2003-2007 Fernando Luis Cacciola Carballal | |
5 | ||
6 | Distributed under the Boost Software License, Version 1.0. | |
7 | (See accompanying file LICENSE_1_0.txt or copy at | |
8 | http://www.boost.org/LICENSE_1_0.txt) | |
9 | ] | |
10 | ||
11 | [section converter<> function object] | |
12 | ||
13 | [section Synopsis] | |
14 | ||
15 | namespace boost { namespace numeric { | |
16 | ||
17 | ||
18 | template<class T, | |
19 | class S, | |
20 | class Traits, = conversion_traits<T,S> | |
21 | class OverflowHandler = def_overflow_handler, | |
22 | class Float2IntRounder = Trunc< typename Traits::source_type >, | |
23 | class RawConverter = raw_converter<Traits>, | |
24 | class UserRangeChecker = UseInternalRangeChecker | |
25 | > | |
26 | struct converter | |
27 | { | |
28 | typedef Traits traits ; | |
29 | ||
30 | typedef typename Traits::source_type source_type ; | |
31 | typedef typename Traits::argument_type argument_type ; | |
32 | typedef typename Traits::result_type result_type ; | |
33 | ||
34 | static result_type convert ( argument_type s ) ; | |
35 | ||
36 | result_type operator() ( argument_type s ) const ; | |
37 | ||
38 | // Internal member functions: | |
39 | ||
40 | static range_check_result out_of_range ( argument_type s ) ; | |
41 | static void validate_range ( argument_type s ) ; | |
42 | static result_type low_level_convert ( argument_type s ) ; | |
43 | static source_type nearbyint ( argument_type s ) ; | |
44 | ||
45 | } ; | |
46 | ||
47 | } } // namespace numeric, boost | |
48 | ||
49 | ||
50 | `boost::numeric::converter<>` is a __SGI_UNARY_FUNCTION__ encapsulating | |
51 | the code to perform a numeric conversion with the direction and | |
52 | properties specified by the Traits template parameter. It can optionally | |
53 | take some [link boost_numericconversion.numeric_converter_policy_classes policies] which can be used to customize its behavior. The | |
54 | `Traits` parameter is not a policy but the parameter that defines | |
55 | the conversion. | |
56 | ||
57 | [endsect] | |
58 | ||
59 | [section Template parameters] | |
60 | ||
61 | [table | |
62 | [[ ][ ]] | |
63 | [[`T`][ | |
64 | The [link boost_numericconversion.definitions.numeric_types Numeric Type] | |
65 | which is the ['Target] of the conversion. | |
66 | ]] | |
67 | [[`S`][ | |
68 | The [link boost_numericconversion.definitions.numeric_types Numeric Type] | |
69 | which is the ['Source] of the conversion. | |
70 | ]] | |
71 | [[`Traits`][ | |
72 | This must be a conversion traits class with the interface of | |
73 | [link boost_numericconversion.conversion_traits___traits_class `boost::numeric::conversion_traits`] | |
74 | ]] | |
75 | [[`OverflowHandler`][ | |
76 | [*Stateless Policy] called to administrate the result of the range checking. | |
77 | ||
78 | It is a [*Function Object] which receives the result of `out_of_range()` | |
79 | and is called inside the `validate_range()` static member function exposed | |
80 | by the converter. | |
81 | ]] | |
82 | [[`Float2IntRounder`][ | |
83 | [*Stateless Policy] which specifies the rounding mode used for float to | |
84 | integral conversions. | |
85 | ||
86 | It supplies the `nearbyint()` static member function exposed by the converter. | |
87 | ]] | |
88 | [[`RawConverter`][ | |
89 | [*Stateless Policy] which is used to perform the actual conversion. | |
90 | ||
91 | It supplies the `low_level_convert()` static member function exposed | |
92 | by the converter. | |
93 | ]] | |
94 | [[`UserRangeChecker`][ | |
95 | ['Special and Optional] [*Stateless Policy] which can be used to override | |
96 | the internal range checking logic. | |
97 | ||
98 | If given, supplies alternative code for the `out_of_range()` and | |
99 | `validate_range()` static member functions exposed by the converter. | |
100 | ]] | |
101 | ] | |
102 | ||
103 | [endsect] | |
104 | ||
105 | [section Member functions] | |
106 | ||
107 | [: `static result_type converter<>::convert ( argument_type s ) ; // throw | |
108 | `] | |
109 | ||
110 | This static member function converts an rvalue of type `source_type` to | |
111 | an rvalue of type `target_type`. | |
112 | ||
113 | If the conversion requires it, it performs a range checking before the conversion | |
114 | and passes the result of the check to the overflow handler policy (the default | |
115 | policy throws an exception if out-of-range is detected) | |
116 | ||
117 | The implementation of this function is actually built from the policies and is | |
118 | basically as follows: | |
119 | ||
120 | result_type converter<>::convert ( argument_type s ) | |
121 | { | |
122 | validate_range(s); // Implemented by the internal range checking logic | |
123 | // (which also calls the OverflowHandler policy) | |
124 | // or externally supplied by the UserRangeChecker policy. | |
125 | ||
126 | s = nearbyint(s); // Externally supplied by the Float2IntRounder policy. | |
127 | // NOTE: This is actually called only for float to int conversions. | |
128 | ||
129 | return low_level_convert(s); // Externally supplied by the RawConverter policy. | |
130 | } | |
131 | ||
132 | `converter<>::operator() const` just calls `convert()` | |
133 | ||
134 | __SPACE__ | |
135 | ||
136 | [: `static range_check_result numeric_converter<>::out_of_range ( argument_type s ) ;`] | |
137 | ||
138 | This [link numeric_conversion_converter_internal internal] static member function | |
139 | determines if the value `s` can be | |
140 | represented by the target type without overflow. | |
141 | ||
142 | It does not determine if the conversion is ['exact]; that is, it does not detect | |
143 | ['inexact] conversions, only ['out-of-range] conversions (see the | |
144 | [link boost_numericconversion.definitions.exact__correctly_rounded_and_out_of_range_representations Definitions] for further details). | |
145 | ||
146 | The return value is of enum type | |
147 | [link boost_numericconversion.numeric_converter_policy_classes.enum_range_check_result `boost::numeric::range_check_result`] | |
148 | ||
149 | The actual code for the range checking logic is optimized for the combined | |
150 | properties of the source and target types. For example, a non-subranged | |
151 | conversion (i.e: `int`->`float`), requires no range checking, so `out_of_range()` | |
152 | returns `cInRange` directly. See the following | |
153 | [link boost_numericconversion.converter___function_object.range_checking_logic table] for more details. | |
154 | ||
155 | If the user supplied a | |
156 | [link boost_numericconversion.numeric_converter_policy_classes.policy_userrangechecker UserRangeChecker] policy, | |
157 | is this policy which implements this function, so the implementation is user | |
158 | defined, although it is expected to perform the same conceptual check and | |
159 | return the appropriate result. | |
160 | ||
161 | __SPACE__ | |
162 | ||
163 | [: `static void numeric_converter<>::validate_range ( argument_type s ) ; // no throw | |
164 | `] | |
165 | ||
166 | This [link numeric_conversion_converter_internal internal] static member function | |
167 | calls out_of_range(s), and passes the | |
168 | result to the [link boost_numericconversion.numeric_converter_policy_classes.policy_overflowhandler OverflowHandler] | |
169 | policy class. | |
170 | ||
171 | For those Target/Source combinations which don't require range checking, this | |
172 | is an empty inline function. | |
173 | ||
174 | If the user supplied a | |
175 | [link boost_numericconversion.numeric_converter_policy_classes.policy_userrangechecker UserRangeChecker] policy, | |
176 | is this policy which implements this function, so the implementation is user | |
177 | defined, although it is expected to perform the same action as the default. | |
178 | In particular, it is expected to pass the result of the check to the overflow handler. | |
179 | ||
180 | __SPACE__ | |
181 | ||
182 | [: `static result_type numeric_converter<>::low_level_convert ( argument_type s ) ;` ] | |
183 | ||
184 | This [link numeric_conversion_converter_internal internal] static member function | |
185 | performs the actual conversion. | |
186 | ||
187 | This function is externally supplied by the | |
188 | [link boost_numericconversion.numeric_converter_policy_classes.policy_rawconverter RawConverter] policy class. | |
189 | ||
190 | __SPACE__ | |
191 | ||
192 | [: `static source_type converter<>::nearbyint ( argument_type s ) ;`] | |
193 | ||
194 | This [link numeric_conversion_converter_internal internal] static member function, | |
195 | which is [_only used] for | |
196 | `float` to `int` conversions, returns an ['integer] value of ['[_floating-point | |
197 | type]] according to some rounding direction. | |
198 | ||
199 | This function is externally supplied by the | |
200 | [link boost_numericconversion.numeric_converter_policy_classes.policy_float2introunder Float2IntRounder] policy class | |
201 | which encapsulates the specific rounding mode. | |
202 | ||
203 | __SPACE__ | |
204 | ||
205 | [#numeric_conversion_converter_internal] | |
206 | ||
207 | [heading Internal Member Functions] | |
208 | ||
209 | These static member functions build the actual conversion code used by `convert()`. | |
210 | The user does not have to call these if calling `convert()`, since `convert()` calls | |
211 | them infernally, but they can be called separately for specific needs. | |
212 | ||
213 | [endsect] | |
214 | ||
215 | [section Range Checking Logic] | |
216 | ||
217 | The following table summarizes the internal range checking logic performed for | |
218 | each combination of the properties of Source and Target. | |
219 | ||
220 | LowestT/HighestT denotes the highest and lowest values of the Target type, respectively. | |
221 | ||
222 | `S(n)` is short for `static_cast<S>(n)` (`S` denotes the Source type). | |
223 | ||
224 | `NONE` indicates that for this case there is no range checking. | |
225 | ||
226 | [pre | |
227 | [^ | |
228 | int_to_int |--> sig_to_sig |--> subranged |--> ( s >= S(LowestT) ) && ( s <= S(HighestT) ) | |
229 | | |--> not subranged |--> NONE | |
230 | | | |
231 | |--> unsig_to_unsig |--> subranged |--> ( s >= S(LowestT) ) && ( s <= S(HighestT) ) | |
232 | | |--> not subranged |--> NONE | |
233 | | | |
234 | |--> sig_to_unsig |--> pos subranged |--> ( s >= S(0) ) && ( s <= S(HighestT) ) | |
235 | | |--> not pos subranged |--> ( s >= S(0) ) | |
236 | | | |
237 | |--> unsig_to_sig |--> subranged |--> ( s <= S(HighestT) ) | |
238 | | |--> not subranged |--> NONE | |
239 | ] | |
240 | [^ | |
241 | int_to_float |--> NONE | |
242 | ] | |
243 | [^ | |
244 | float_to_int |--> round_to_zero |--> ( s > S(LowestT)-S(1) ) && ( s < S(HighestT)+S(1) ) | |
245 | |--> round_to_even_nearest |--> ( s >= S(LowestT)-S(0.5) ) && ( s < S(HighestT)+S(0.5) ) | |
246 | |--> round_to_infinity |--> ( s > S(LowestT)-S(1) ) && ( s <= S(HighestT) ) | |
247 | |--> round_to_neg_infinity |--> ( s >= S(LowestT) ) && ( s < S(HighestT)+S(1) ) | |
248 | ] | |
249 | [^ | |
250 | float_to_float |--> subranged |--> ( s >= S(LowestT) ) && ( s <= S(HighestT) ) | |
251 | |--> not subranged |--> NONE | |
252 | ] | |
253 | ] | |
254 | ||
255 | ||
256 | ||
257 | [endsect] | |
258 | ||
259 | [section Examples] | |
260 | ||
261 | #include <cassert> | |
262 | #include <boost/numeric/conversion/converter.hpp> | |
263 | ||
264 | int main() { | |
265 | ||
266 | typedef boost::numeric::converter<int,double> Double2Int ; | |
267 | ||
268 | int x = Double2Int::convert(2.0); | |
269 | assert ( x == 2 ); | |
270 | ||
271 | int y = Double2Int()(3.14); // As a function object. | |
272 | assert ( y == 3 ) ; // The default rounding is trunc. | |
273 | ||
274 | try | |
275 | { | |
276 | double m = boost::numeric::bounds<double>::highest(); | |
277 | int z = Double2Int::convert(m); // By default throws positive_overflow() | |
278 | } | |
279 | catch ( boost::numeric::positive_overflow const& ) | |
280 | { | |
281 | } | |
282 | ||
283 | return 0; | |
284 | } | |
285 | ||
286 | [endsect] | |
287 | ||
288 | [endsect] | |
289 | ||
290 | ||
291 | ||
292 | ||
293 |