]>
Commit | Line | Data |
---|---|---|
1 | // (c) Copyright Fernando Luis Cacciola Carballal 2000-2004 | |
2 | // Use, modification, and distribution is subject to the Boost Software | |
3 | // License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at | |
4 | // http://www.boost.org/LICENSE_1_0.txt) | |
5 | ||
6 | // See library home page at http://www.boost.org/libs/numeric/conversion | |
7 | // | |
8 | // Contact the author at: fernando_cacciola@hotmail.com | |
9 | // | |
10 | #ifndef BOOST_NUMERIC_CONVERSION_DETAIL_CONVERTER_FLC_12NOV2002_HPP | |
11 | #define BOOST_NUMERIC_CONVERSION_DETAIL_CONVERTER_FLC_12NOV2002_HPP | |
12 | ||
13 | #include <functional> | |
14 | ||
15 | #include "boost/numeric/conversion/detail/meta.hpp" | |
16 | #include "boost/numeric/conversion/detail/conversion_traits.hpp" | |
17 | #include "boost/numeric/conversion/bounds.hpp" | |
18 | ||
19 | #include "boost/type_traits/is_same.hpp" | |
20 | ||
21 | #include "boost/mpl/integral_c.hpp" | |
22 | ||
23 | namespace boost { namespace numeric { namespace convdetail | |
24 | { | |
25 | // Integral Constants representing rounding modes | |
26 | typedef mpl::integral_c<std::float_round_style, std::round_toward_zero> round2zero_c ; | |
27 | typedef mpl::integral_c<std::float_round_style, std::round_to_nearest> round2nearest_c ; | |
28 | typedef mpl::integral_c<std::float_round_style, std::round_toward_infinity> round2inf_c ; | |
29 | typedef mpl::integral_c<std::float_round_style, std::round_toward_neg_infinity> round2neg_inf_c ; | |
30 | ||
31 | // Metafunction: | |
32 | // | |
33 | // for_round_style<RoundStyle,RoundToZero,RoundToNearest,RoundToInf,RoundToNegInf>::type | |
34 | // | |
35 | // {RoundStyle} Integral Constant specifying a round style as declared above. | |
36 | // {RoundToZero,RoundToNearest,RoundToInf,RoundToNegInf} arbitrary types. | |
37 | // | |
38 | // Selects one of the 4 types according to the value of RoundStyle. | |
39 | // | |
40 | template<class RoundStyle,class RoundToZero,class RoundToNearest,class RoundToInf,class RoundToNegInf> | |
41 | struct for_round_style | |
42 | { | |
43 | typedef ct_switch4<RoundStyle | |
44 | , round2zero_c, round2nearest_c, round2inf_c // round2neg_inf_c | |
45 | , RoundToZero , RoundToNearest , RoundToInf , RoundToNegInf | |
46 | > selector ; | |
47 | ||
48 | typedef typename selector::type type ; | |
49 | } ; | |
50 | ||
51 | ||
52 | ||
53 | ||
54 | ||
55 | ||
56 | ||
57 | ||
58 | ||
59 | ||
60 | ||
61 | ||
62 | ||
63 | ||
64 | ||
65 | ||
66 | ||
67 | ||
68 | //-------------------------------------------------------------------------- | |
69 | // Range Checking Logic. | |
70 | // | |
71 | // The range checking logic is built up by combining 1 or 2 predicates. | |
72 | // Each predicate is encapsulated in a template class and exposes | |
73 | // the static member function 'apply'. | |
74 | // | |
75 | //-------------------------------------------------------------------------- | |
76 | ||
77 | ||
78 | // Because a particular logic can combine either 1 or two predicates, the following | |
79 | // tags are used to allow the predicate applier to receive 2 preds, but optimize away | |
80 | // one of them if it is 'non-applicable' | |
81 | struct non_applicable { typedef mpl::false_ do_apply ; } ; | |
82 | struct applicable { typedef mpl::true_ do_apply ; } ; | |
83 | ||
84 | ||
85 | //-------------------------------------------------------------------------- | |
86 | // | |
87 | // Range Checking Logic implementations. | |
88 | // | |
89 | // The following classes, collectivelly named 'Predicates', are instantiated within | |
90 | // the corresponding range checkers. | |
91 | // Their static member function 'apply' is called to perform the actual range checking logic. | |
92 | //-------------------------------------------------------------------------- | |
93 | ||
94 | // s < Lowest(T) ? cNegOverflow : cInRange | |
95 | // | |
96 | template<class Traits> | |
97 | struct LT_LoT : applicable | |
98 | { | |
99 | typedef typename Traits::target_type T ; | |
100 | typedef typename Traits::source_type S ; | |
101 | typedef typename Traits::argument_type argument_type ; | |
102 | ||
103 | static range_check_result apply ( argument_type s ) | |
104 | { | |
105 | return s < static_cast<S>(bounds<T>::lowest()) ? cNegOverflow : cInRange ; | |
106 | } | |
107 | } ; | |
108 | ||
109 | // s < 0 ? cNegOverflow : cInRange | |
110 | // | |
111 | template<class Traits> | |
112 | struct LT_Zero : applicable | |
113 | { | |
114 | typedef typename Traits::source_type S ; | |
115 | typedef typename Traits::argument_type argument_type ; | |
116 | ||
117 | static range_check_result apply ( argument_type s ) | |
118 | { | |
119 | return s < static_cast<S>(0) ? cNegOverflow : cInRange ; | |
120 | } | |
121 | } ; | |
122 | ||
123 | // s <= Lowest(T)-1 ? cNegOverflow : cInRange | |
124 | // | |
125 | template<class Traits> | |
126 | struct LE_PrevLoT : applicable | |
127 | { | |
128 | typedef typename Traits::target_type T ; | |
129 | typedef typename Traits::source_type S ; | |
130 | typedef typename Traits::argument_type argument_type ; | |
131 | ||
132 | static range_check_result apply ( argument_type s ) | |
133 | { | |
134 | return s <= static_cast<S>(bounds<T>::lowest()) - static_cast<S>(1.0) | |
135 | ? cNegOverflow : cInRange ; | |
136 | } | |
137 | } ; | |
138 | ||
139 | // s < Lowest(T)-0.5 ? cNegOverflow : cInRange | |
140 | // | |
141 | template<class Traits> | |
142 | struct LT_HalfPrevLoT : applicable | |
143 | { | |
144 | typedef typename Traits::target_type T ; | |
145 | typedef typename Traits::source_type S ; | |
146 | typedef typename Traits::argument_type argument_type ; | |
147 | ||
148 | static range_check_result apply ( argument_type s ) | |
149 | { | |
150 | return s < static_cast<S>(bounds<T>::lowest()) - static_cast<S>(0.5) | |
151 | ? cNegOverflow : cInRange ; | |
152 | } | |
153 | } ; | |
154 | ||
155 | // s > Highest(T) ? cPosOverflow : cInRange | |
156 | // | |
157 | template<class Traits> | |
158 | struct GT_HiT : applicable | |
159 | { | |
160 | typedef typename Traits::target_type T ; | |
161 | typedef typename Traits::source_type S ; | |
162 | typedef typename Traits::argument_type argument_type ; | |
163 | ||
164 | static range_check_result apply ( argument_type s ) | |
165 | { | |
166 | return s > static_cast<S>(bounds<T>::highest()) | |
167 | ? cPosOverflow : cInRange ; | |
168 | } | |
169 | } ; | |
170 | ||
171 | // s >= Lowest(T) + 1 ? cPosOverflow : cInRange | |
172 | // | |
173 | template<class Traits> | |
174 | struct GE_SuccHiT : applicable | |
175 | { | |
176 | typedef typename Traits::target_type T ; | |
177 | typedef typename Traits::source_type S ; | |
178 | typedef typename Traits::argument_type argument_type ; | |
179 | ||
180 | static range_check_result apply ( argument_type s ) | |
181 | { | |
182 | return s >= static_cast<S>(bounds<T>::highest()) + static_cast<S>(1.0) | |
183 | ? cPosOverflow : cInRange ; | |
184 | } | |
185 | } ; | |
186 | ||
187 | // s >= Lowest(T) + 0.5 ? cPosgOverflow : cInRange | |
188 | // | |
189 | template<class Traits> | |
190 | struct GT_HalfSuccHiT : applicable | |
191 | { | |
192 | typedef typename Traits::target_type T ; | |
193 | typedef typename Traits::source_type S ; | |
194 | typedef typename Traits::argument_type argument_type ; | |
195 | ||
196 | static range_check_result apply ( argument_type s ) | |
197 | { | |
198 | return s >= static_cast<S>(bounds<T>::highest()) + static_cast<S>(0.5) | |
199 | ? cPosOverflow : cInRange ; | |
200 | } | |
201 | } ; | |
202 | ||
203 | ||
204 | //-------------------------------------------------------------------------- | |
205 | // | |
206 | // Predicate Combiner. | |
207 | // | |
208 | // This helper classes are used to possibly combine the range checking logic | |
209 | // individually performed by the predicates | |
210 | // | |
211 | //-------------------------------------------------------------------------- | |
212 | ||
213 | ||
214 | // Applies both predicates: first 'PredA', and if it equals 'cInRange', 'PredB' | |
215 | template<class PredA, class PredB> | |
216 | struct applyBoth | |
217 | { | |
218 | typedef typename PredA::argument_type argument_type ; | |
219 | ||
220 | static range_check_result apply ( argument_type s ) | |
221 | { | |
222 | range_check_result r = PredA::apply(s) ; | |
223 | if ( r == cInRange ) | |
224 | r = PredB::apply(s); | |
225 | return r ; | |
226 | } | |
227 | } ; | |
228 | ||
229 | template<class PredA, class PredB> | |
230 | struct combine | |
231 | { | |
232 | typedef applyBoth<PredA,PredB> Both ; | |
233 | typedef void NNone ; // 'None' is defined as a macro in (/usr/X11R6/include/X11/X.h) | |
234 | ||
235 | typedef typename PredA::do_apply do_applyA ; | |
236 | typedef typename PredB::do_apply do_applyB ; | |
237 | ||
238 | typedef typename for_both<do_applyA, do_applyB, Both, PredA, PredB, NNone>::type type ; | |
239 | } ; | |
240 | ||
241 | ||
242 | ||
243 | ||
244 | ||
245 | ||
246 | ||
247 | ||
248 | ||
249 | ||
250 | ||
251 | ||
252 | //-------------------------------------------------------------------------- | |
253 | // Range Checker classes. | |
254 | // | |
255 | // The following classes are VISIBLE base classes of the user-level converter<> class. | |
256 | // They supply the optimized 'out_of_range()' and 'validate_range()' static member functions | |
257 | // visible in the user interface. | |
258 | // | |
259 | //-------------------------------------------------------------------------- | |
260 | ||
261 | // Dummy range checker. | |
262 | template<class Traits> | |
263 | struct dummy_range_checker | |
264 | { | |
265 | typedef typename Traits::argument_type argument_type ; | |
266 | ||
267 | static range_check_result out_of_range ( argument_type ) { return cInRange ; } | |
268 | static void validate_range ( argument_type ) {} | |
269 | } ; | |
270 | ||
271 | // Generic range checker. | |
272 | // | |
273 | // All the range checking logic for all possible combinations of source and target | |
274 | // can be arranged in terms of one or two predicates, which test overflow on both neg/pos 'sides' | |
275 | // of the ranges. | |
276 | // | |
277 | // These predicates are given here as IsNegOverflow and IsPosOverflow. | |
278 | // | |
279 | template<class Traits, class IsNegOverflow, class IsPosOverflow, class OverflowHandler> | |
280 | struct generic_range_checker | |
281 | { | |
282 | typedef OverflowHandler overflow_handler ; | |
283 | ||
284 | typedef typename Traits::argument_type argument_type ; | |
285 | ||
286 | static range_check_result out_of_range ( argument_type s ) | |
287 | { | |
288 | typedef typename combine<IsNegOverflow,IsPosOverflow>::type Predicate ; | |
289 | ||
290 | return Predicate::apply(s); | |
291 | } | |
292 | ||
293 | static void validate_range ( argument_type s ) | |
294 | { OverflowHandler()( out_of_range(s) ) ; } | |
295 | } ; | |
296 | ||
297 | ||
298 | ||
299 | //-------------------------------------------------------------------------- | |
300 | // | |
301 | // Selectors for the optimized Range Checker class. | |
302 | // | |
303 | //-------------------------------------------------------------------------- | |
304 | ||
305 | template<class Traits,class OverflowHandler> | |
306 | struct GetRC_Sig2Sig_or_Unsig2Unsig | |
307 | { | |
308 | typedef dummy_range_checker<Traits> Dummy ; | |
309 | ||
310 | typedef LT_LoT<Traits> Pred1 ; | |
311 | typedef GT_HiT<Traits> Pred2 ; | |
312 | ||
313 | typedef generic_range_checker<Traits,Pred1,Pred2,OverflowHandler> Normal ; | |
314 | ||
315 | typedef typename Traits::subranged subranged ; | |
316 | ||
317 | typedef typename mpl::if_<subranged,Normal,Dummy>::type type ; | |
318 | } ; | |
319 | ||
320 | template<class Traits, class OverflowHandler> | |
321 | struct GetRC_Sig2Unsig | |
322 | { | |
323 | typedef LT_Zero<Traits> Pred1 ; | |
324 | typedef GT_HiT <Traits> Pred2 ; | |
325 | ||
326 | typedef generic_range_checker<Traits,Pred1,Pred2,OverflowHandler> ChoiceA ; | |
327 | ||
328 | typedef generic_range_checker<Traits,Pred1,non_applicable,OverflowHandler> ChoiceB ; | |
329 | ||
330 | typedef typename Traits::target_type T ; | |
331 | typedef typename Traits::source_type S ; | |
332 | ||
333 | typedef typename subranged_Unsig2Sig<S,T>::type oposite_subranged ; | |
334 | ||
335 | typedef typename mpl::not_<oposite_subranged>::type positively_subranged ; | |
336 | ||
337 | typedef typename mpl::if_<positively_subranged,ChoiceA,ChoiceB>::type type ; | |
338 | } ; | |
339 | ||
340 | template<class Traits, class OverflowHandler> | |
341 | struct GetRC_Unsig2Sig | |
342 | { | |
343 | typedef GT_HiT<Traits> Pred1 ; | |
344 | ||
345 | typedef generic_range_checker<Traits,non_applicable,Pred1,OverflowHandler> type ; | |
346 | } ; | |
347 | ||
348 | template<class Traits,class OverflowHandler> | |
349 | struct GetRC_Int2Int | |
350 | { | |
351 | typedef GetRC_Sig2Sig_or_Unsig2Unsig<Traits,OverflowHandler> Sig2SigQ ; | |
352 | typedef GetRC_Sig2Unsig <Traits,OverflowHandler> Sig2UnsigQ ; | |
353 | typedef GetRC_Unsig2Sig <Traits,OverflowHandler> Unsig2SigQ ; | |
354 | typedef Sig2SigQ Unsig2UnsigQ ; | |
355 | ||
356 | typedef typename Traits::sign_mixture sign_mixture ; | |
357 | ||
358 | typedef typename | |
359 | for_sign_mixture<sign_mixture,Sig2SigQ,Sig2UnsigQ,Unsig2SigQ,Unsig2UnsigQ>::type | |
360 | selector ; | |
361 | ||
362 | typedef typename selector::type type ; | |
363 | } ; | |
364 | ||
365 | template<class Traits> | |
366 | struct GetRC_Int2Float | |
367 | { | |
368 | typedef dummy_range_checker<Traits> type ; | |
369 | } ; | |
370 | ||
371 | template<class Traits, class OverflowHandler, class Float2IntRounder> | |
372 | struct GetRC_Float2Int | |
373 | { | |
374 | typedef LE_PrevLoT <Traits> Pred1 ; | |
375 | typedef GE_SuccHiT <Traits> Pred2 ; | |
376 | typedef LT_HalfPrevLoT<Traits> Pred3 ; | |
377 | typedef GT_HalfSuccHiT<Traits> Pred4 ; | |
378 | typedef GT_HiT <Traits> Pred5 ; | |
379 | typedef LT_LoT <Traits> Pred6 ; | |
380 | ||
381 | typedef generic_range_checker<Traits,Pred1,Pred2,OverflowHandler> ToZero ; | |
382 | typedef generic_range_checker<Traits,Pred3,Pred4,OverflowHandler> ToNearest ; | |
383 | typedef generic_range_checker<Traits,Pred1,Pred5,OverflowHandler> ToInf ; | |
384 | typedef generic_range_checker<Traits,Pred6,Pred2,OverflowHandler> ToNegInf ; | |
385 | ||
386 | typedef typename Float2IntRounder::round_style round_style ; | |
387 | ||
388 | typedef typename for_round_style<round_style,ToZero,ToNearest,ToInf,ToNegInf>::type type ; | |
389 | } ; | |
390 | ||
391 | template<class Traits, class OverflowHandler> | |
392 | struct GetRC_Float2Float | |
393 | { | |
394 | typedef dummy_range_checker<Traits> Dummy ; | |
395 | ||
396 | typedef LT_LoT<Traits> Pred1 ; | |
397 | typedef GT_HiT<Traits> Pred2 ; | |
398 | ||
399 | typedef generic_range_checker<Traits,Pred1,Pred2,OverflowHandler> Normal ; | |
400 | ||
401 | typedef typename Traits::subranged subranged ; | |
402 | ||
403 | typedef typename mpl::if_<subranged,Normal,Dummy>::type type ; | |
404 | } ; | |
405 | ||
406 | template<class Traits, class OverflowHandler, class Float2IntRounder> | |
407 | struct GetRC_BuiltIn2BuiltIn | |
408 | { | |
409 | typedef GetRC_Int2Int<Traits,OverflowHandler> Int2IntQ ; | |
410 | typedef GetRC_Int2Float<Traits> Int2FloatQ ; | |
411 | typedef GetRC_Float2Int<Traits,OverflowHandler,Float2IntRounder> Float2IntQ ; | |
412 | typedef GetRC_Float2Float<Traits,OverflowHandler> Float2FloatQ ; | |
413 | ||
414 | typedef typename Traits::int_float_mixture int_float_mixture ; | |
415 | ||
416 | typedef typename for_int_float_mixture<int_float_mixture, Int2IntQ, Int2FloatQ, Float2IntQ, Float2FloatQ>::type selector ; | |
417 | ||
418 | typedef typename selector::type type ; | |
419 | } ; | |
420 | ||
421 | template<class Traits, class OverflowHandler, class Float2IntRounder> | |
422 | struct GetRC | |
423 | { | |
424 | typedef GetRC_BuiltIn2BuiltIn<Traits,OverflowHandler,Float2IntRounder> BuiltIn2BuiltInQ ; | |
425 | ||
426 | typedef dummy_range_checker<Traits> Dummy ; | |
427 | ||
428 | typedef mpl::identity<Dummy> DummyQ ; | |
429 | ||
430 | typedef typename Traits::udt_builtin_mixture udt_builtin_mixture ; | |
431 | ||
432 | typedef typename for_udt_builtin_mixture<udt_builtin_mixture,BuiltIn2BuiltInQ,DummyQ,DummyQ,DummyQ>::type selector ; | |
433 | ||
434 | typedef typename selector::type type ; | |
435 | } ; | |
436 | ||
437 | ||
438 | ||
439 | ||
440 | //-------------------------------------------------------------------------- | |
441 | // Converter classes. | |
442 | // | |
443 | // The following classes are VISIBLE base classes of the user-level converter<> class. | |
444 | // They supply the optimized 'nearbyint()' and 'convert()' static member functions | |
445 | // visible in the user interface. | |
446 | // | |
447 | //-------------------------------------------------------------------------- | |
448 | ||
449 | // | |
450 | // Trivial Converter : used when (cv-unqualified) T == (cv-unqualified) S | |
451 | // | |
452 | template<class Traits> | |
453 | struct trivial_converter_impl : public std::unary_function< BOOST_DEDUCED_TYPENAME Traits::argument_type | |
454 | ,BOOST_DEDUCED_TYPENAME Traits::result_type | |
455 | > | |
456 | ,public dummy_range_checker<Traits> | |
457 | { | |
458 | typedef Traits traits ; | |
459 | ||
460 | typedef typename Traits::source_type source_type ; | |
461 | typedef typename Traits::argument_type argument_type ; | |
462 | typedef typename Traits::result_type result_type ; | |
463 | ||
464 | static result_type low_level_convert ( argument_type s ) { return s ; } | |
465 | static source_type nearbyint ( argument_type s ) { return s ; } | |
466 | static result_type convert ( argument_type s ) { return s ; } | |
467 | } ; | |
468 | ||
469 | ||
470 | // | |
471 | // Rounding Converter : used for float to integral conversions. | |
472 | // | |
473 | template<class Traits,class RangeChecker,class RawConverter,class Float2IntRounder> | |
474 | struct rounding_converter : public std::unary_function< BOOST_DEDUCED_TYPENAME Traits::argument_type | |
475 | ,BOOST_DEDUCED_TYPENAME Traits::result_type | |
476 | > | |
477 | ,public RangeChecker | |
478 | ,public Float2IntRounder | |
479 | ,public RawConverter | |
480 | { | |
481 | typedef RangeChecker RangeCheckerBase ; | |
482 | typedef Float2IntRounder Float2IntRounderBase ; | |
483 | typedef RawConverter RawConverterBase ; | |
484 | ||
485 | typedef Traits traits ; | |
486 | ||
487 | typedef typename Traits::source_type source_type ; | |
488 | typedef typename Traits::argument_type argument_type ; | |
489 | typedef typename Traits::result_type result_type ; | |
490 | ||
491 | static result_type convert ( argument_type s ) | |
492 | { | |
493 | RangeCheckerBase::validate_range(s); | |
494 | source_type s1 = Float2IntRounderBase::nearbyint(s); | |
495 | return RawConverterBase::low_level_convert(s1); | |
496 | } | |
497 | } ; | |
498 | ||
499 | ||
500 | // | |
501 | // Non-Rounding Converter : used for all other conversions. | |
502 | // | |
503 | template<class Traits,class RangeChecker,class RawConverter> | |
504 | struct non_rounding_converter : public std::unary_function< BOOST_DEDUCED_TYPENAME Traits::argument_type | |
505 | ,BOOST_DEDUCED_TYPENAME Traits::result_type | |
506 | > | |
507 | ,public RangeChecker | |
508 | ,public RawConverter | |
509 | { | |
510 | typedef RangeChecker RangeCheckerBase ; | |
511 | typedef RawConverter RawConverterBase ; | |
512 | ||
513 | typedef Traits traits ; | |
514 | ||
515 | typedef typename Traits::source_type source_type ; | |
516 | typedef typename Traits::argument_type argument_type ; | |
517 | typedef typename Traits::result_type result_type ; | |
518 | ||
519 | static source_type nearbyint ( argument_type s ) { return s ; } | |
520 | ||
521 | static result_type convert ( argument_type s ) | |
522 | { | |
523 | RangeCheckerBase::validate_range(s); | |
524 | return RawConverterBase::low_level_convert(s); | |
525 | } | |
526 | } ; | |
527 | ||
528 | ||
529 | ||
530 | ||
531 | //-------------------------------------------------------------------------- | |
532 | // | |
533 | // Selectors for the optimized Converter class. | |
534 | // | |
535 | //-------------------------------------------------------------------------- | |
536 | ||
537 | template<class Traits,class OverflowHandler,class Float2IntRounder,class RawConverter, class UserRangeChecker> | |
538 | struct get_non_trivial_converter | |
539 | { | |
540 | typedef GetRC<Traits,OverflowHandler,Float2IntRounder> InternalRangeCheckerQ ; | |
541 | ||
542 | typedef is_same<UserRangeChecker,UseInternalRangeChecker> use_internal_RC ; | |
543 | ||
544 | typedef mpl::identity<UserRangeChecker> UserRangeCheckerQ ; | |
545 | ||
546 | typedef typename | |
547 | mpl::eval_if<use_internal_RC,InternalRangeCheckerQ,UserRangeCheckerQ>::type | |
548 | RangeChecker ; | |
549 | ||
550 | typedef non_rounding_converter<Traits,RangeChecker,RawConverter> NonRounding ; | |
551 | typedef rounding_converter<Traits,RangeChecker,RawConverter,Float2IntRounder> Rounding ; | |
552 | ||
553 | typedef mpl::identity<NonRounding> NonRoundingQ ; | |
554 | typedef mpl::identity<Rounding> RoundingQ ; | |
555 | ||
556 | typedef typename Traits::int_float_mixture int_float_mixture ; | |
557 | ||
558 | typedef typename | |
559 | for_int_float_mixture<int_float_mixture, NonRoundingQ, NonRoundingQ, RoundingQ, NonRoundingQ>::type | |
560 | selector ; | |
561 | ||
562 | typedef typename selector::type type ; | |
563 | } ; | |
564 | ||
565 | template< class Traits | |
566 | ,class OverflowHandler | |
567 | ,class Float2IntRounder | |
568 | ,class RawConverter | |
569 | ,class UserRangeChecker | |
570 | > | |
571 | struct get_converter_impl | |
572 | { | |
573 | #if BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT( 0x0561 ) ) | |
574 | // bcc55 prefers sometimes template parameters to be explicit local types. | |
575 | // (notice that is is illegal to reuse the names like this) | |
576 | typedef Traits Traits ; | |
577 | typedef OverflowHandler OverflowHandler ; | |
578 | typedef Float2IntRounder Float2IntRounder ; | |
579 | typedef RawConverter RawConverter ; | |
580 | typedef UserRangeChecker UserRangeChecker ; | |
581 | #endif | |
582 | ||
583 | typedef trivial_converter_impl<Traits> Trivial ; | |
584 | typedef mpl::identity <Trivial> TrivialQ ; | |
585 | ||
586 | typedef get_non_trivial_converter< Traits | |
587 | ,OverflowHandler | |
588 | ,Float2IntRounder | |
589 | ,RawConverter | |
590 | ,UserRangeChecker | |
591 | > NonTrivialQ ; | |
592 | ||
593 | typedef typename Traits::trivial trivial ; | |
594 | ||
595 | typedef typename mpl::eval_if<trivial,TrivialQ,NonTrivialQ>::type type ; | |
596 | } ; | |
597 | ||
598 | } } } // namespace boost::numeric::convdetail | |
599 | ||
600 | #endif | |
601 | ||
602 |