]> git.proxmox.com Git - ceph.git/blame - 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
CommitLineData
7c673cae
FG
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
11fdf7f2
TL
11// 02 Jun 14 Remove VC6 workarounds.
12// 16 Jul 11 Bugfixes for VC6.
7c673cae
FG
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
7c673cae
FG
58namespace 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; }
7c673cae
FG
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)
20effc67 234#elif defined(BOOST_BORLANDC)
7c673cae
FG
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)
20effc67 251#elif defined(BOOST_BORLANDC)
7c673cae
FG
252# pragma option pop
253# endif
254 } // namespace detail
255
256#endif
257
258 template<typename Target, typename Source>
11fdf7f2 259 inline Target numeric_cast(Source arg)
7c673cae
FG
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)
20effc67 288#elif defined(BOOST_BORLANDC)
7c673cae
FG
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)
20effc67 296#elif defined(BOOST_BORLANDC)
7c673cae
FG
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
7c673cae
FG
306} // namespace boost
307
308#endif // BOOST_OLD_NUMERIC_CAST_HPP