From 7470535162d00ca1b0d2fca62551dc2ded3f11c0 Mon Sep 17 00:00:00 2001 From: Dave Abrahams Date: Thu, 19 Oct 2000 19:14:03 +0000 Subject: [PATCH] Fix numeric_cast<> bugs with floating types. [SVN r8008] --- include/boost/cast.hpp | 73 ++++++++++++++++++++++++++++++++++++++---- 1 file changed, 66 insertions(+), 7 deletions(-) diff --git a/include/boost/cast.hpp b/include/boost/cast.hpp index 2283bb1..f7bb927 100644 --- a/include/boost/cast.hpp +++ b/include/boost/cast.hpp @@ -9,6 +9,7 @@ // See http://www.boost.org for most recent version including documentation. // Revision History +// 19 Oct 00 Fix numeric_cast for floating-point types (Dave Abrahams) // 15 Jul 00 Suppress numeric_cast warnings for GCC, Borland and MSVC (Dave Abrahams) // 30 Jun 00 More MSVC6 wordarounds. See comments below. (Dave Abrahams) // 28 Jun 00 Removed implicit_cast<>. See comment below. (Beman Dawes) @@ -124,7 +125,43 @@ namespace boost #endif #ifndef BOOST_NO_LIMITS_COMPILE_TIME_CONSTANTS - // less_than_type_min - + + namespace detail + { + template struct numeric_min_select; + + template<> + struct numeric_min_select + { + template + struct limits : std::numeric_limits + { + static inline T min() + { + return std::numeric_limits::min() >= 0 + // unary minus causes integral promotion, thus the static_cast<> + ? static_cast(-std::numeric_limits::max()) + : std::numeric_limits::min(); + } + }; + }; + + template<> + struct numeric_min_select + { + template + struct limits : std::numeric_limits {}; + }; + + // Move to namespace boost in utility.hpp? + template + struct fixed_numeric_limits + : public numeric_min_select::is_signed>::limits + { + }; + } + +// less_than_type_min - // x_is_signed should be numeric_limits::is_signed // y_is_signed should be numeric_limits::is_signed // y_min should be numeric_limits::min() @@ -204,6 +241,30 @@ namespace boost static inline bool check(X x, Y) { return static_cast(static_cast(x)) != x; } }; + +#else // use #pragma hacks if available + + namespace detail { +# if BOOST_MSVC +# pragma warning(push) +# pragma warning(disable : 4018) +# pragma warning(disable : 4146) +# endif + // Move to namespace boost in utility.hpp? + template + struct fixed_numeric_limits : public std::numeric_limits + { + static inline T min() + { + return std::numeric_limits::is_signed && std::numeric_limits::min() >= 0 + ? -std::numeric_limits::max() : std::numeric_limits::min(); + } + }; +# if BOOST_MSVC +# pragma warning(pop) +# endif + } + #endif template @@ -211,7 +272,7 @@ namespace boost { // typedefs abbreviating respective trait classes typedef std::numeric_limits arg_traits; - typedef std::numeric_limits result_traits; + typedef detail::fixed_numeric_limits result_traits; #ifndef BOOST_NO_LIMITS_COMPILE_TIME_CONSTANTS // typedefs that act as compile time assertions @@ -234,10 +295,9 @@ namespace boost # pragma warning(push) # pragma warning(disable : 4018) # endif - if ( (arg < 0 && !result_traits::is_signed) || // loss of negative range - (arg_traits::is_signed && - arg < result_traits::min()) || // underflow - arg > result_traits::max() ) // overflow + if ((arg < 0 && !result_traits::is_signed) // loss of negative range + || (arg_traits::is_signed && arg < result_traits::min()) // underflow + || arg > result_traits::max()) // overflow # if BOOST_MSVC # pragma warning(pop) # endif @@ -272,4 +332,3 @@ namespace boost } // namespace boost #endif // BOOST_CAST_HPP -