Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-01-18 09:42:47

0001 //  boost cast.hpp header file  ----------------------------------------------//
0002 
0003 //  (C) Copyright Kevlin Henney and Dave Abrahams 1999.
0004 //  Distributed under the Boost
0005 //  Software License, Version 1.0. (See accompanying file
0006 //  LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
0007 
0008 //  See http://www.boost.org/libs/conversion for Documentation.
0009 
0010 //  Revision History
0011 //  02 Jun 14  Remove VC6 workarounds.
0012 //  16 Jul 11  Bugfixes for VC6.
0013 //  23 JUN 05  Code extracted from /boost/cast.hpp into this new header.
0014 //             Keeps this legacy version of numeric_cast<> for old compilers
0015 //             wich can't compile the new version in /boost/numeric/conversion/cast.hpp
0016 //             (Fernando Cacciola)
0017 //  02 Apr 01  Removed BOOST_NO_LIMITS workarounds and included
0018 //             <boost/limits.hpp> instead (the workaround did not
0019 //             actually compile when BOOST_NO_LIMITS was defined in
0020 //             any case, so we loose nothing). (John Maddock)
0021 //  21 Jan 01  Undid a bug I introduced yesterday. numeric_cast<> never
0022 //             worked with stock GCC; trying to get it to do that broke
0023 //             vc-stlport.
0024 //  20 Jan 01  Moved BOOST_NO_LIMITS_COMPILE_TIME_CONSTANTS to config.hpp.
0025 //             Removed unused BOOST_EXPLICIT_TARGET macro. Moved
0026 //             boost::detail::type to boost/type.hpp. Made it compile with
0027 //             stock gcc again (Dave Abrahams)
0028 //  29 Nov 00  Remove nested namespace cast, cleanup spacing before Formal
0029 //             Review (Beman Dawes)
0030 //  19 Oct 00  Fix numeric_cast for floating-point types (Dave Abrahams)
0031 //  15 Jul 00  Suppress numeric_cast warnings for GCC, Borland and MSVC
0032 //             (Dave Abrahams)
0033 //  30 Jun 00  More MSVC6 wordarounds.  See comments below.  (Dave Abrahams)
0034 //  28 Jun 00  Removed implicit_cast<>.  See comment below. (Beman Dawes)
0035 //  27 Jun 00  More MSVC6 workarounds
0036 //  15 Jun 00  Add workarounds for MSVC6
0037 //   2 Feb 00  Remove bad_numeric_cast ";" syntax error (Doncho Angelov)
0038 //  26 Jan 00  Add missing throw() to bad_numeric_cast::what(0 (Adam Levar)
0039 //  29 Dec 99  Change using declarations so usages in other namespaces work
0040 //             correctly (Dave Abrahams)
0041 //  23 Sep 99  Change polymorphic_downcast assert to also detect M.I. errors
0042 //             as suggested Darin Adler and improved by Valentin Bonnard.
0043 //   2 Sep 99  Remove controversial asserts, simplify, rename.
0044 //  30 Aug 99  Move to cast.hpp, replace value_cast with numeric_cast,
0045 //             place in nested namespace.
0046 //   3 Aug 99  Initial version
0047 
0048 #ifndef BOOST_OLD_NUMERIC_CAST_HPP
0049 #define BOOST_OLD_NUMERIC_CAST_HPP
0050 
0051 # include <boost/config.hpp>
0052 # include <cassert>
0053 # include <typeinfo>
0054 # include <boost/type.hpp>
0055 # include <boost/limits.hpp>
0056 # include <boost/numeric/conversion/converter_policies.hpp>
0057 
0058 namespace boost
0059 {
0060   using numeric::bad_numeric_cast;
0061 
0062 //  LEGACY numeric_cast [only for some old broken compilers] --------------------------------------//
0063 
0064 //  Contributed by Kevlin Henney
0065 
0066 //  numeric_cast  ------------------------------------------------------------//
0067 
0068 #if !defined(BOOST_NO_LIMITS_COMPILE_TIME_CONSTANTS) || defined(BOOST_SGI_CPP_LIMITS)
0069 
0070     namespace detail
0071     {
0072       template <class T>
0073       struct signed_numeric_limits : std::numeric_limits<T>
0074       {
0075              static inline T min BOOST_PREVENT_MACRO_SUBSTITUTION ()
0076          {
0077              return (std::numeric_limits<T>::min)() >= 0
0078                      // unary minus causes integral promotion, thus the static_cast<>
0079                      ? static_cast<T>(-(std::numeric_limits<T>::max)())
0080                      : (std::numeric_limits<T>::min)();
0081          };
0082       };
0083 
0084       // Move to namespace boost in utility.hpp?
0085       template <class T, bool specialized>
0086       struct fixed_numeric_limits_base
0087           : public if_true< std::numeric_limits<T>::is_signed >
0088            ::BOOST_NESTED_TEMPLATE then< signed_numeric_limits<T>,
0089                             std::numeric_limits<T>
0090                    >::type
0091       {};
0092 
0093       template <class T>
0094       struct fixed_numeric_limits
0095           : fixed_numeric_limits_base<T,(std::numeric_limits<T>::is_specialized)>
0096       {};
0097 
0098 # ifdef BOOST_HAS_LONG_LONG
0099       // cover implementations which supply no specialization for long
0100       // long / unsigned long long. Not intended to be full
0101       // numeric_limits replacements, but good enough for numeric_cast<>
0102       template <>
0103       struct fixed_numeric_limits_base< ::boost::long_long_type, false>
0104       {
0105           BOOST_STATIC_CONSTANT(bool, is_specialized = true);
0106           BOOST_STATIC_CONSTANT(bool, is_signed = true);
0107           static  ::boost::long_long_type max BOOST_PREVENT_MACRO_SUBSTITUTION ()
0108           {
0109 #  ifdef LONGLONG_MAX
0110               return LONGLONG_MAX;
0111 #  else
0112               return 9223372036854775807LL; // hope this is portable
0113 #  endif
0114           }
0115 
0116           static  ::boost::long_long_type min BOOST_PREVENT_MACRO_SUBSTITUTION ()
0117           {
0118 #  ifdef LONGLONG_MIN
0119               return LONGLONG_MIN;
0120 #  else
0121                return -( 9223372036854775807LL )-1; // hope this is portable
0122 #  endif
0123           }
0124       };
0125 
0126       template <>
0127       struct fixed_numeric_limits_base< ::boost::ulong_long_type, false>
0128       {
0129           BOOST_STATIC_CONSTANT(bool, is_specialized = true);
0130           BOOST_STATIC_CONSTANT(bool, is_signed = false);
0131           static  ::boost::ulong_long_type max BOOST_PREVENT_MACRO_SUBSTITUTION ()
0132           {
0133 #  ifdef ULONGLONG_MAX
0134               return ULONGLONG_MAX;
0135 #  else
0136               return 0xffffffffffffffffULL; // hope this is portable
0137 #  endif
0138           }
0139 
0140           static  ::boost::ulong_long_type min BOOST_PREVENT_MACRO_SUBSTITUTION () { return 0; }
0141       };
0142 # endif
0143     } // namespace detail
0144 
0145 // less_than_type_min -
0146   //    x_is_signed should be numeric_limits<X>::is_signed
0147   //    y_is_signed should be numeric_limits<Y>::is_signed
0148   //    y_min should be numeric_limits<Y>::min()
0149   //
0150   //    check(x, y_min) returns true iff x < y_min without invoking comparisons
0151   //    between signed and unsigned values.
0152   //
0153   //    "poor man's partial specialization" is in use here.
0154     template <bool x_is_signed, bool y_is_signed>
0155     struct less_than_type_min
0156     {
0157         template <class X, class Y>
0158         static bool check(X x, Y y_min)
0159             { return x < y_min; }
0160     };
0161 
0162     template <>
0163     struct less_than_type_min<false, true>
0164     {
0165         template <class X, class Y>
0166         static bool check(X, Y)
0167             { return false; }
0168     };
0169 
0170     template <>
0171     struct less_than_type_min<true, false>
0172     {
0173         template <class X, class Y>
0174         static bool check(X x, Y)
0175             { return x < 0; }
0176     };
0177 
0178   // greater_than_type_max -
0179   //    same_sign should be:
0180   //            numeric_limits<X>::is_signed == numeric_limits<Y>::is_signed
0181   //    y_max should be numeric_limits<Y>::max()
0182   //
0183   //    check(x, y_max) returns true iff x > y_max without invoking comparisons
0184   //    between signed and unsigned values.
0185   //
0186   //    "poor man's partial specialization" is in use here.
0187     template <bool same_sign, bool x_is_signed>
0188     struct greater_than_type_max;
0189 
0190     template<>
0191     struct greater_than_type_max<true, true>
0192     {
0193         template <class X, class Y>
0194         static inline bool check(X x, Y y_max)
0195             { return x > y_max; }
0196     };
0197 
0198     template <>
0199     struct greater_than_type_max<false, true>
0200     {
0201         // What does the standard say about this? I think it's right, and it
0202         // will work with every compiler I know of.
0203         template <class X, class Y>
0204         static inline bool check(X x, Y)
0205             { return x >= 0 && static_cast<X>(static_cast<Y>(x)) != x; }
0206     };
0207 
0208     template<>
0209     struct greater_than_type_max<true, false>
0210     {
0211         template <class X, class Y>
0212         static inline bool check(X x, Y y_max)
0213             { return x > y_max; }
0214     };
0215 
0216     template <>
0217     struct greater_than_type_max<false, false>
0218     {
0219         // What does the standard say about this? I think it's right, and it
0220         // will work with every compiler I know of.
0221         template <class X, class Y>
0222         static inline bool check(X x, Y)
0223             { return static_cast<X>(static_cast<Y>(x)) != x; }
0224     };
0225 
0226 #else // use #pragma hacks if available
0227 
0228   namespace detail
0229   {
0230 # if BOOST_MSVC
0231 #  pragma warning(push)
0232 #  pragma warning(disable : 4018)
0233 #  pragma warning(disable : 4146)
0234 #elif defined(BOOST_BORLANDC)
0235 #  pragma option push -w-8041
0236 # endif
0237 
0238        // Move to namespace boost in utility.hpp?
0239        template <class T>
0240        struct fixed_numeric_limits : public std::numeric_limits<T>
0241        {
0242            static inline T min BOOST_PREVENT_MACRO_SUBSTITUTION ()
0243            {
0244                return std::numeric_limits<T>::is_signed && (std::numeric_limits<T>::min)() >= 0
0245                    ? T(-(std::numeric_limits<T>::max)()) : (std::numeric_limits<T>::min)();
0246            }
0247        };
0248 
0249 # if BOOST_MSVC
0250 #  pragma warning(pop)
0251 #elif defined(BOOST_BORLANDC)
0252 #  pragma option pop
0253 # endif
0254   } // namespace detail
0255 
0256 #endif
0257 
0258     template<typename Target, typename Source>
0259     inline Target numeric_cast(Source arg)
0260     {
0261         // typedefs abbreviating respective trait classes
0262         typedef detail::fixed_numeric_limits<Source> arg_traits;
0263         typedef detail::fixed_numeric_limits<Target> result_traits;
0264 
0265 #if defined(BOOST_STRICT_CONFIG) \
0266     || (!defined(__HP_aCC) || __HP_aCC > 33900) \
0267          && (!defined(BOOST_NO_LIMITS_COMPILE_TIME_CONSTANTS) \
0268              || defined(BOOST_SGI_CPP_LIMITS))
0269         // typedefs that act as compile time assertions
0270         // (to be replaced by boost compile time assertions
0271         // as and when they become available and are stable)
0272         typedef bool argument_must_be_numeric[arg_traits::is_specialized];
0273         typedef bool result_must_be_numeric[result_traits::is_specialized];
0274 
0275         const bool arg_is_signed = arg_traits::is_signed;
0276         const bool result_is_signed = result_traits::is_signed;
0277         const bool same_sign = arg_is_signed == result_is_signed;
0278 
0279         if (less_than_type_min<arg_is_signed, result_is_signed>::check(arg, (result_traits::min)())
0280             || greater_than_type_max<same_sign, arg_is_signed>::check(arg, (result_traits::max)())
0281             )
0282 
0283 #else // We need to use #pragma hacks if available
0284 
0285 # if BOOST_MSVC
0286 #  pragma warning(push)
0287 #  pragma warning(disable : 4018)
0288 #elif defined(BOOST_BORLANDC)
0289 #pragma option push -w-8012
0290 # endif
0291         if ((arg < 0 && !result_traits::is_signed)  // loss of negative range
0292              || (arg_traits::is_signed && arg < (result_traits::min)())  // underflow
0293              || arg > (result_traits::max)())            // overflow
0294 # if BOOST_MSVC
0295 #  pragma warning(pop)
0296 #elif defined(BOOST_BORLANDC)
0297 #pragma option pop
0298 # endif
0299 #endif
0300         {
0301             throw bad_numeric_cast();
0302         }
0303         return static_cast<Target>(arg);
0304     } // numeric_cast
0305 
0306 } // namespace boost
0307 
0308 #endif  // BOOST_OLD_NUMERIC_CAST_HPP