]> git.lyx.org Git - features.git/blob - 3rdparty/boost/boost/numeric/conversion/detail/old_numeric_cast.hpp
Update to boost 1.68
[features.git] / 3rdparty / boost / boost / numeric / conversion / detail / old_numeric_cast.hpp
1 //  boost cast.hpp header file  ----------------------------------------------//
2
3 //  (C) Copyright Kevlin Henney and Dave Abrahams 1999.
4 //  Distributed under the Boost
5 //  Software License, Version 1.0. (See accompanying file
6 //  LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
7
8 //  See http://www.boost.org/libs/conversion for Documentation.
9
10 //  Revision History
11 //  02 Jun 14  Remove VC6 workarounds.
12 //  16 Jul 11  Bugfixes for VC6.
13 //  23 JUN 05  Code extracted from /boost/cast.hpp into this new header.
14 //             Keeps this legacy version of numeric_cast<> for old compilers
15 //             wich can't compile the new version in /boost/numeric/conversion/cast.hpp
16 //             (Fernando Cacciola)
17 //  02 Apr 01  Removed BOOST_NO_LIMITS workarounds and included
18 //             <boost/limits.hpp> instead (the workaround did not
19 //             actually compile when BOOST_NO_LIMITS was defined in
20 //             any case, so we loose nothing). (John Maddock)
21 //  21 Jan 01  Undid a bug I introduced yesterday. numeric_cast<> never
22 //             worked with stock GCC; trying to get it to do that broke
23 //             vc-stlport.
24 //  20 Jan 01  Moved BOOST_NO_LIMITS_COMPILE_TIME_CONSTANTS to config.hpp.
25 //             Removed unused BOOST_EXPLICIT_TARGET macro. Moved
26 //             boost::detail::type to boost/type.hpp. Made it compile with
27 //             stock gcc again (Dave Abrahams)
28 //  29 Nov 00  Remove nested namespace cast, cleanup spacing before Formal
29 //             Review (Beman Dawes)
30 //  19 Oct 00  Fix numeric_cast for floating-point types (Dave Abrahams)
31 //  15 Jul 00  Suppress numeric_cast warnings for GCC, Borland and MSVC
32 //             (Dave Abrahams)
33 //  30 Jun 00  More MSVC6 wordarounds.  See comments below.  (Dave Abrahams)
34 //  28 Jun 00  Removed implicit_cast<>.  See comment below. (Beman Dawes)
35 //  27 Jun 00  More MSVC6 workarounds
36 //  15 Jun 00  Add workarounds for MSVC6
37 //   2 Feb 00  Remove bad_numeric_cast ";" syntax error (Doncho Angelov)
38 //  26 Jan 00  Add missing throw() to bad_numeric_cast::what(0 (Adam Levar)
39 //  29 Dec 99  Change using declarations so usages in other namespaces work
40 //             correctly (Dave Abrahams)
41 //  23 Sep 99  Change polymorphic_downcast assert to also detect M.I. errors
42 //             as suggested Darin Adler and improved by Valentin Bonnard.
43 //   2 Sep 99  Remove controversial asserts, simplify, rename.
44 //  30 Aug 99  Move to cast.hpp, replace value_cast with numeric_cast,
45 //             place in nested namespace.
46 //   3 Aug 99  Initial version
47
48 #ifndef BOOST_OLD_NUMERIC_CAST_HPP
49 #define BOOST_OLD_NUMERIC_CAST_HPP
50
51 # include <boost/config.hpp>
52 # include <cassert>
53 # include <typeinfo>
54 # include <boost/type.hpp>
55 # include <boost/limits.hpp>
56 # include <boost/numeric/conversion/converter_policies.hpp>
57
58 namespace boost
59 {
60   using numeric::bad_numeric_cast;
61
62 //  LEGACY numeric_cast [only for some old broken compilers] --------------------------------------//
63
64 //  Contributed by Kevlin Henney
65
66 //  numeric_cast  ------------------------------------------------------------//
67
68 #if !defined(BOOST_NO_LIMITS_COMPILE_TIME_CONSTANTS) || defined(BOOST_SGI_CPP_LIMITS)
69
70     namespace detail
71     {
72       template <class T>
73       struct signed_numeric_limits : std::numeric_limits<T>
74       {
75              static inline T min BOOST_PREVENT_MACRO_SUBSTITUTION ()
76          {
77              return (std::numeric_limits<T>::min)() >= 0
78                      // unary minus causes integral promotion, thus the static_cast<>
79                      ? static_cast<T>(-(std::numeric_limits<T>::max)())
80                      : (std::numeric_limits<T>::min)();
81          };
82       };
83
84       // Move to namespace boost in utility.hpp?
85       template <class T, bool specialized>
86       struct fixed_numeric_limits_base
87           : public if_true< std::numeric_limits<T>::is_signed >
88            ::BOOST_NESTED_TEMPLATE then< signed_numeric_limits<T>,
89                             std::numeric_limits<T>
90                    >::type
91       {};
92
93       template <class T>
94       struct fixed_numeric_limits
95           : fixed_numeric_limits_base<T,(std::numeric_limits<T>::is_specialized)>
96       {};
97
98 # ifdef BOOST_HAS_LONG_LONG
99       // cover implementations which supply no specialization for long
100       // long / unsigned long long. Not intended to be full
101       // numeric_limits replacements, but good enough for numeric_cast<>
102       template <>
103       struct fixed_numeric_limits_base< ::boost::long_long_type, false>
104       {
105           BOOST_STATIC_CONSTANT(bool, is_specialized = true);
106           BOOST_STATIC_CONSTANT(bool, is_signed = true);
107           static  ::boost::long_long_type max BOOST_PREVENT_MACRO_SUBSTITUTION ()
108           {
109 #  ifdef LONGLONG_MAX
110               return LONGLONG_MAX;
111 #  else
112               return 9223372036854775807LL; // hope this is portable
113 #  endif
114           }
115
116           static  ::boost::long_long_type min BOOST_PREVENT_MACRO_SUBSTITUTION ()
117           {
118 #  ifdef LONGLONG_MIN
119               return LONGLONG_MIN;
120 #  else
121                return -( 9223372036854775807LL )-1; // hope this is portable
122 #  endif
123           }
124       };
125
126       template <>
127       struct fixed_numeric_limits_base< ::boost::ulong_long_type, false>
128       {
129           BOOST_STATIC_CONSTANT(bool, is_specialized = true);
130           BOOST_STATIC_CONSTANT(bool, is_signed = false);
131           static  ::boost::ulong_long_type max BOOST_PREVENT_MACRO_SUBSTITUTION ()
132           {
133 #  ifdef ULONGLONG_MAX
134               return ULONGLONG_MAX;
135 #  else
136               return 0xffffffffffffffffULL; // hope this is portable
137 #  endif
138           }
139
140           static  ::boost::ulong_long_type min BOOST_PREVENT_MACRO_SUBSTITUTION () { return 0; }
141       };
142 # endif
143     } // namespace detail
144
145 // less_than_type_min -
146   //    x_is_signed should be numeric_limits<X>::is_signed
147   //    y_is_signed should be numeric_limits<Y>::is_signed
148   //    y_min should be numeric_limits<Y>::min()
149   //
150   //    check(x, y_min) returns true iff x < y_min without invoking comparisons
151   //    between signed and unsigned values.
152   //
153   //    "poor man's partial specialization" is in use here.
154     template <bool x_is_signed, bool y_is_signed>
155     struct less_than_type_min
156     {
157         template <class X, class Y>
158         static bool check(X x, Y y_min)
159             { return x < y_min; }
160     };
161
162     template <>
163     struct less_than_type_min<false, true>
164     {
165         template <class X, class Y>
166         static bool check(X, Y)
167             { return false; }
168     };
169
170     template <>
171     struct less_than_type_min<true, false>
172     {
173         template <class X, class Y>
174         static bool check(X x, Y)
175             { return x < 0; }
176     };
177
178   // greater_than_type_max -
179   //    same_sign should be:
180   //            numeric_limits<X>::is_signed == numeric_limits<Y>::is_signed
181   //    y_max should be numeric_limits<Y>::max()
182   //
183   //    check(x, y_max) returns true iff x > y_max without invoking comparisons
184   //    between signed and unsigned values.
185   //
186   //    "poor man's partial specialization" is in use here.
187     template <bool same_sign, bool x_is_signed>
188     struct greater_than_type_max;
189
190     template<>
191     struct greater_than_type_max<true, true>
192     {
193         template <class X, class Y>
194         static inline bool check(X x, Y y_max)
195             { return x > y_max; }
196     };
197
198     template <>
199     struct greater_than_type_max<false, true>
200     {
201         // What does the standard say about this? I think it's right, and it
202         // will work with every compiler I know of.
203         template <class X, class Y>
204         static inline bool check(X x, Y)
205             { return x >= 0 && static_cast<X>(static_cast<Y>(x)) != x; }
206     };
207
208     template<>
209     struct greater_than_type_max<true, false>
210     {
211         template <class X, class Y>
212         static inline bool check(X x, Y y_max)
213             { return x > y_max; }
214     };
215
216     template <>
217     struct greater_than_type_max<false, false>
218     {
219         // What does the standard say about this? I think it's right, and it
220         // will work with every compiler I know of.
221         template <class X, class Y>
222         static inline bool check(X x, Y)
223             { return static_cast<X>(static_cast<Y>(x)) != x; }
224     };
225
226 #else // use #pragma hacks if available
227
228   namespace detail
229   {
230 # if BOOST_MSVC
231 #  pragma warning(push)
232 #  pragma warning(disable : 4018)
233 #  pragma warning(disable : 4146)
234 #elif defined(__BORLANDC__)
235 #  pragma option push -w-8041
236 # endif
237
238        // Move to namespace boost in utility.hpp?
239        template <class T>
240        struct fixed_numeric_limits : public std::numeric_limits<T>
241        {
242            static inline T min BOOST_PREVENT_MACRO_SUBSTITUTION ()
243            {
244                return std::numeric_limits<T>::is_signed && (std::numeric_limits<T>::min)() >= 0
245                    ? T(-(std::numeric_limits<T>::max)()) : (std::numeric_limits<T>::min)();
246            }
247        };
248
249 # if BOOST_MSVC
250 #  pragma warning(pop)
251 #elif defined(__BORLANDC__)
252 #  pragma option pop
253 # endif
254   } // namespace detail
255
256 #endif
257
258     template<typename Target, typename Source>
259     inline Target numeric_cast(Source arg)
260     {
261         // typedefs abbreviating respective trait classes
262         typedef detail::fixed_numeric_limits<Source> arg_traits;
263         typedef detail::fixed_numeric_limits<Target> result_traits;
264
265 #if defined(BOOST_STRICT_CONFIG) \
266     || (!defined(__HP_aCC) || __HP_aCC > 33900) \
267          && (!defined(BOOST_NO_LIMITS_COMPILE_TIME_CONSTANTS) \
268              || defined(BOOST_SGI_CPP_LIMITS))
269         // typedefs that act as compile time assertions
270         // (to be replaced by boost compile time assertions
271         // as and when they become available and are stable)
272         typedef bool argument_must_be_numeric[arg_traits::is_specialized];
273         typedef bool result_must_be_numeric[result_traits::is_specialized];
274
275         const bool arg_is_signed = arg_traits::is_signed;
276         const bool result_is_signed = result_traits::is_signed;
277         const bool same_sign = arg_is_signed == result_is_signed;
278
279         if (less_than_type_min<arg_is_signed, result_is_signed>::check(arg, (result_traits::min)())
280             || greater_than_type_max<same_sign, arg_is_signed>::check(arg, (result_traits::max)())
281             )
282
283 #else // We need to use #pragma hacks if available
284
285 # if BOOST_MSVC
286 #  pragma warning(push)
287 #  pragma warning(disable : 4018)
288 #elif defined(__BORLANDC__)
289 #pragma option push -w-8012
290 # endif
291         if ((arg < 0 && !result_traits::is_signed)  // loss of negative range
292              || (arg_traits::is_signed && arg < (result_traits::min)())  // underflow
293              || arg > (result_traits::max)())            // overflow
294 # if BOOST_MSVC
295 #  pragma warning(pop)
296 #elif defined(__BORLANDC__)
297 #pragma option pop
298 # endif
299 #endif
300         {
301             throw bad_numeric_cast();
302         }
303         return static_cast<Target>(arg);
304     } // numeric_cast
305
306 } // namespace boost
307
308 #endif  // BOOST_OLD_NUMERIC_CAST_HPP