]> git.lyx.org Git - lyx.git/blob - boost/boost/cast.hpp
leave formula when pressing end at the end of a formula (and similarly
[lyx.git] / boost / boost / cast.hpp
1 //  boost cast.hpp header file  ----------------------------------------------//
2
3 //  (C) Copyright boost.org 1999. Permission to copy, use, modify, sell
4 //  and distribute this software is granted provided this copyright
5 //  notice appears in all copies. This software is provided "as is" without
6 //  express or implied warranty, and with no claim as to its suitability for
7 //  any purpose.
8
9 //  See http://www.boost.org for most recent version including documentation.
10
11 //  Revision History
12 //  02 Apr 01  Removed BOOST_NO_LIMITS workarounds and included 
13 //             <boost/limits.hpp> instead (the workaround did not 
14 //             actually compile when BOOST_NO_LIMITS was defined in 
15 //             any case, so we loose nothing). (John Maddock)
16 //  21 Jan 01  Undid a bug I introduced yesterday. numeric_cast<> never
17 //             worked with stock GCC; trying to get it to do that broke
18 //             vc-stlport.
19 //  20 Jan 01  Moved BOOST_NO_LIMITS_COMPILE_TIME_CONSTANTS to config.hpp.
20 //             Removed unused BOOST_EXPLICIT_TARGET macro. Moved
21 //             boost::detail::type to boost/type.hpp. Made it compile with
22 //             stock gcc again (Dave Abrahams)
23 //  29 Nov 00  Remove nested namespace cast, cleanup spacing before Formal
24 //             Review (Beman Dawes)
25 //  19 Oct 00  Fix numeric_cast for floating-point types (Dave Abrahams)
26 //  15 Jul 00  Suppress numeric_cast warnings for GCC, Borland and MSVC
27 //             (Dave Abrahams)
28 //  30 Jun 00  More MSVC6 wordarounds.  See comments below.  (Dave Abrahams)
29 //  28 Jun 00  Removed implicit_cast<>.  See comment below. (Beman Dawes)
30 //  27 Jun 00  More MSVC6 workarounds 
31 //  15 Jun 00  Add workarounds for MSVC6
32 //   2 Feb 00  Remove bad_numeric_cast ";" syntax error (Doncho Angelov)
33 //  26 Jan 00  Add missing throw() to bad_numeric_cast::what(0 (Adam Levar)
34 //  29 Dec 99  Change using declarations so usages in other namespaces work
35 //             correctly (Dave Abrahams)
36 //  23 Sep 99  Change polymorphic_downcast assert to also detect M.I. errors
37 //             as suggested Darin Adler and improved by Valentin Bonnard.  
38 //   2 Sep 99  Remove controversial asserts, simplify, rename.
39 //  30 Aug 99  Move to cast.hpp, replace value_cast with numeric_cast,
40 //             place in nested namespace.
41 //   3 Aug 99  Initial version
42
43 #ifndef BOOST_CAST_HPP
44 #define BOOST_CAST_HPP
45
46 # include <boost/config.hpp>
47 # include <cassert>
48 # include <typeinfo>
49 # include <boost/type.hpp>
50 # include <boost/limits.hpp>
51
52 //  It has been demonstrated numerous times that MSVC 6.0 fails silently at link
53 //  time if you use a template function which has template parameters that don't
54 //  appear in the function's argument list.
55 //
56 //  TODO: Add this to config.hpp?
57 # if defined(BOOST_MSVC) && BOOST_MSVC <= 1200 // 1200 = VC6
58 #  define BOOST_EXPLICIT_DEFAULT_TARGET , ::boost::type<Target>* = 0
59 # else
60 #  define BOOST_EXPLICIT_DEFAULT_TARGET
61 # endif
62
63 namespace boost
64 {
65 //  See the documentation for descriptions of how to choose between
66 //  static_cast<>, dynamic_cast<>, polymorphic_cast<> and polymorphic_downcast<>
67
68 //  polymorphic_cast  --------------------------------------------------------//
69
70     //  Runtime checked polymorphic downcasts and crosscasts.
71     //  Suggested in The C++ Programming Language, 3rd Ed, Bjarne Stroustrup, 
72     //  section 15.8 exercise 1, page 425.
73
74     template <class Target, class Source>
75     inline Target polymorphic_cast(Source* x BOOST_EXPLICIT_DEFAULT_TARGET)
76     {
77         Target tmp = dynamic_cast<Target>(x);
78         if ( tmp == 0 ) throw std::bad_cast();
79         return tmp;
80     }
81
82 //  polymorphic_downcast  ----------------------------------------------------//
83
84     //  assert() checked polymorphic downcast.  Crosscasts prohibited.
85
86     //  WARNING: Because this cast uses assert(), it violates the One Definition
87     //  Rule if NDEBUG is inconsistently defined across translation units.
88
89     //  Contributed by Dave Abrahams
90
91     template <class Target, class Source>
92     inline Target polymorphic_downcast(Source* x BOOST_EXPLICIT_DEFAULT_TARGET)
93     {
94         assert( dynamic_cast<Target>(x) == x );  // detect logic error
95         return static_cast<Target>(x);
96     }
97
98 //  implicit_cast  -----------------------------------------------------------//
99 //
100 //  Removed due to uncertain purpose.  Use either numeric_cast (see below)
101 //  or static_cast according to the need. 
102
103 //  numeric_cast and related exception  --------------------------------------//
104
105 //  Contributed by Kevlin Henney
106
107 //  bad_numeric_cast  --------------------------------------------------------//
108
109     // exception used to indicate runtime numeric_cast failure
110     class bad_numeric_cast : public std::bad_cast
111     {
112     public:
113         // constructors, destructors and assignment operator defaulted
114
115         // function inlined for brevity and consistency with rest of library
116         virtual const char *what() const throw()
117         {
118             return "bad numeric cast: loss of range in numeric_cast";
119         }
120     };
121
122 //  numeric_cast  ------------------------------------------------------------//
123
124 #if !defined(BOOST_NO_LIMITS_COMPILE_TIME_CONSTANTS) || defined(BOOST_SGI_CPP_LIMITS)
125   
126     namespace detail
127     {
128        template <bool is_signed> struct numeric_min_select;
129     
130        template<>
131        struct numeric_min_select<true>
132        {
133          template <class T>
134          struct limits : std::numeric_limits<T>
135          {
136          static inline T min()
137 # ifndef __GNUC__ // bug workaround courtesy Jens Maurer
138              {
139                  return std::numeric_limits<T>::min() >= 0
140                      // unary minus causes integral promotion, thus the static_cast<>
141                      ? static_cast<T>(-std::numeric_limits<T>::max())
142                      : std::numeric_limits<T>::min();
143              }
144 # else
145                  ;
146 # endif
147          };
148        };
149
150 # ifdef __GNUC__ // bug workaround courtesy Jens Maurer
151       template<> template<class T>
152       inline T numeric_min_select<true>::limits<T>::min()
153       {
154            return std::numeric_limits<T>::min() >= 0
155                // unary minus causes integral promotion, thus the static_cast<>
156                ? static_cast<T>(-std::numeric_limits<T>::max())
157                : std::numeric_limits<T>::min();
158       }
159 # endif
160     
161       template<>
162       struct numeric_min_select<false>
163       {
164           template <class T>
165           struct limits : std::numeric_limits<T> {};
166       };
167       
168       // Move to namespace boost in utility.hpp?
169       template <class T>
170       struct fixed_numeric_limits
171           : public numeric_min_select<
172                        std::numeric_limits<T>::is_signed 
173                    >::template limits<T>
174       {
175       };
176     } // namespace detail
177   
178 // less_than_type_min -
179   //    x_is_signed should be numeric_limits<X>::is_signed
180   //    y_is_signed should be numeric_limits<Y>::is_signed
181   //    y_min should be numeric_limits<Y>::min()
182   //
183   //    check(x, y_min) returns true iff x < y_min without invoking comparisons
184   //    between signed and unsigned values.
185   //
186   //    "poor man's partial specialization" is in use here.
187     template <bool x_is_signed, bool y_is_signed>
188     struct less_than_type_min
189     {
190         template <class X, class Y>
191         static bool check(X x, Y y_min)
192             { return x < y_min; }
193     };
194
195     template <>
196     struct less_than_type_min<false, true>
197     {
198         template <class X, class Y>
199         static bool check(X, Y)
200             { return false; }
201     };
202     
203     template <>
204     struct less_than_type_min<true, false>
205     {
206         template <class X, class Y>
207         static bool check(X x, Y)
208             { return x < 0; }
209     };
210     
211   // greater_than_type_max -
212   //    same_sign should be:
213   //            numeric_limits<X>::is_signed == numeric_limits<Y>::is_signed
214   //    y_max should be numeric_limits<Y>::max()
215   //
216   //    check(x, y_max) returns true iff x > y_max without invoking comparisons
217   //    between signed and unsigned values.
218   //
219   //    "poor man's partial specialization" is in use here.
220     template <bool same_sign, bool x_is_signed>
221     struct greater_than_type_max;
222
223     template<>
224     struct greater_than_type_max<true, true>
225     {
226         template <class X, class Y>
227         static inline bool check(X x, Y y_max)
228             { return x > y_max; }
229     };
230
231     template <>
232     struct greater_than_type_max<false, true>
233     {
234         // What does the standard say about this? I think it's right, and it
235         // will work with every compiler I know of.
236         template <class X, class Y>
237         static inline bool check(X x, Y)
238             { return x >= 0 && static_cast<X>(static_cast<Y>(x)) != x; }
239     };
240
241     template<>
242     struct greater_than_type_max<true, false>
243     {
244         template <class X, class Y>
245         static inline bool check(X x, Y y_max)
246             { return x > y_max; }
247     };
248
249     template <>
250     struct greater_than_type_max<false, false>
251     {
252         // What does the standard say about this? I think it's right, and it
253         // will work with every compiler I know of.
254         template <class X, class Y>
255         static inline bool check(X x, Y)
256             { return static_cast<X>(static_cast<Y>(x)) != x; }
257     };
258   
259 #else // use #pragma hacks if available
260
261   namespace detail
262   {
263 # if BOOST_MSVC
264 #  pragma warning(push)
265 #  pragma warning(disable : 4018)
266 #  pragma warning(disable : 4146)
267 #elif defined(__BORLANDC__)
268 #  pragma option push -w-8041
269 # endif
270
271        // Move to namespace boost in utility.hpp?
272        template <class T>
273        struct fixed_numeric_limits : public std::numeric_limits<T>
274        {
275            static inline T min()
276            {
277                return std::numeric_limits<T>::is_signed && std::numeric_limits<T>::min() >= 0
278                    ? T(-std::numeric_limits<T>::max()) : std::numeric_limits<T>::min();
279            }
280        };
281   
282 # if BOOST_MSVC
283 #  pragma warning(pop)
284 #elif defined(__BORLANDC__)
285 #  pragma option pop
286 # endif
287   } // namespace detail
288   
289 #endif
290   
291     template<typename Target, typename Source>
292     inline Target numeric_cast(Source arg BOOST_EXPLICIT_DEFAULT_TARGET)
293     {
294         // typedefs abbreviating respective trait classes
295         typedef std::numeric_limits<Source> arg_traits;
296         typedef detail::fixed_numeric_limits<Target> result_traits;
297         
298 #if !defined(BOOST_NO_LIMITS_COMPILE_TIME_CONSTANTS) || defined(BOOST_SGI_CPP_LIMITS)
299         // typedefs that act as compile time assertions
300         // (to be replaced by boost compile time assertions
301         // as and when they become available and are stable)
302         typedef bool argument_must_be_numeric[arg_traits::is_specialized];
303         typedef bool result_must_be_numeric[result_traits::is_specialized];
304
305         const bool arg_is_signed = arg_traits::is_signed;
306         const bool result_is_signed = result_traits::is_signed;
307         const bool same_sign = arg_is_signed == result_is_signed;
308
309         if (less_than_type_min<arg_is_signed, result_is_signed>::check(arg, result_traits::min())
310             || greater_than_type_max<same_sign, arg_is_signed>::check(arg, result_traits::max())
311             )
312             
313 #else // We need to use #pragma hacks if available
314             
315 # if BOOST_MSVC
316 #  pragma warning(push)
317 #  pragma warning(disable : 4018)
318 #elif defined(__BORLANDC__)
319 #pragma option push -w-8012
320 # endif
321         if ((arg < 0 && !result_traits::is_signed)  // loss of negative range
322              || (arg_traits::is_signed && arg < result_traits::min())  // underflow
323              || arg > result_traits::max())            // overflow
324 # if BOOST_MSVC
325 #  pragma warning(pop)
326 #elif defined(__BORLANDC__)
327 #pragma option pop
328 # endif
329 #endif
330         {
331             throw bad_numeric_cast();
332         }
333         return static_cast<Target>(arg);
334     } // numeric_cast
335
336 #  undef BOOST_EXPLICIT_DEFAULT_TARGET
337
338 } // namespace boost
339
340 #endif  // BOOST_CAST_HPP