]> git.proxmox.com Git - ceph.git/blob - ceph/src/boost/boost/numeric/conversion/detail/old_numeric_cast.hpp
import quincy beta 17.1.0
[ceph.git] / ceph / src / 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(BOOST_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(BOOST_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(BOOST_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(BOOST_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