
"Fernando Cacciola" <fernando_cacciola@hotmail.com> wrote in message news:<c64iag$bes$1@sea.gmane.org>...
"David Abrahams" <dave@boost-consulting.com> escribió en el mensaje news:u3c6ywa5w.fsf@boost-consulting.com...
"Dill, John" <john-dill@uiowa.edu> writes:
I am wondering about the use-case of numeric_cast in this sample.
unsigned char uchar_max = std::numeric_limits<unsigned char>::max(); char schar_value = 0;
try { schar_value = boost::numeric_cast<char>( uchar_max ); } catch ( boost::bad_numeric_cast ) { std::cout << "Overflow occurred..." << std::endl; }
When I execute this sample, I don't get the exception. What's the background on this behavior? I'm using gcc 3.3.1.
FWIW, there are known problems with numeric_cast, but a numeric conversion library that replaces the existing implementation has been accepted into Boost. We are just waiting for Fernando Cacciola to check it in. Fernando?
Indeed. The accepted numeric conversions library handles this case properly (throwing). Right now I'm technically on vacation until next Monday. I'll start working with the review comments right next week. I'll check it in on CVS after I made the neccesary changes.
Anyway, users can download the review version from here:
http://personales.ciudad.com.ar/fernando_cacciola/numeric_conversions.zip
or
http://groups.yahoo.com/group/boost/files/numeric_conversions.zip
Fernando Cacciola
Thanks. Well, I didn't know this was out there so I wrote my own numeric_cast which works for those cases I described. It's not boost oriented, but all of the concepts should be convertible to mpl. Maybe it will be useful to someone. Best, John /*! * \file numeric_cast.hpp * \brief A cast which protects against silent underflow or overflow casts. */ #include <uiro/type/ct_if.hpp> #include <uiro/type/typelist.hpp> #include <uiro/utility/limits.hpp> namespace uiro { //! Exception used to indicate underflow in a numeric cast. class bad_numeric_cast : public std::bad_cast { public: virtual const char* what() const throw() { return "bad numeric cast"; } }; //! Exception used to indicate underflow in a numeric cast. class numeric_cast_underflow : public bad_numeric_cast { public: virtual const char* what() const throw() { return "underflow in numeric_cast"; } }; //! Exception used to indicate overflow in a numeric cast. class numeric_cast_overflow : public bad_numeric_cast { public: virtual const char* what() const throw() { return "overflow in numeric_cast"; } }; namespace internal { //! Selects the type with the largest minimum value. template <typename T1, typename T2> struct promote_min_traits { typedef TYPELIST_10(unsigned char, unsigned short, unsigned int, unsigned long, char, short, int, long, float, double) promote_order_typelist; enum { index1 = uiro::type::index_of<promote_order_typelist, T1>::value }; enum { index2 = uiro::type::index_of<promote_order_typelist, T2>::value }; typedef typename uiro::type::ct_if< uiro::type::greater_than_equal<index1,index2>::result, T1, T2>::result result; }; //! Selects the type with the largest maximum value. template <typename T1, typename T2> struct promote_max_traits { // May run into issues if sizeof(int) != sizeof(long) typedef TYPELIST_10(char, unsigned char, short, unsigned short, int, long, unsigned int, unsigned long, float, double) promote_order_typelist; enum { index1 = uiro::type::index_of<promote_order_typelist, T1>::value }; enum { index2 = uiro::type::index_of<promote_order_typelist, T2>::value }; typedef typename uiro::type::ct_if< uiro::type::greater_than_equal<index1,index2>::result, T1, T2>::result result; }; struct unsigned_tag {}; struct signed_tag {}; //! A numeric cast helper which handles the an unsigned source type //! without generating compiler warnings. template <typename Target, typename Source> inline Target numeric_cast_helper( Source arg, unsigned_tag ) { // An overflow condition. if ( static_cast<typename promote_max_traits<Source, Target>::result>( arg ) > static_cast<typename promote_max_traits<Source, Target>::result>( std::numeric_limits<Target>::max() ) ) { throw numeric_cast_overflow(); } return static_cast<Target>(arg); } //! A numeric cast helper which handles the an signed source type. template <typename Target, typename Source> inline Target numeric_cast_helper( Source arg, signed_tag ) { // A loss of negative range, or more generally an underflow. if ( ( arg < 0 && !std::numeric_limits<Target>::is_signed ) || ( static_cast<typename promote_min_traits<Source, Target>::result>( arg ) < static_cast<typename promote_min_traits<Source, Target>::result>( std::numeric_limits<Target>::min() ) ) ) { throw numeric_cast_underflow(); } // A loss of positive range. if ( static_cast<typename promote_max_traits<Source, Target>::result>( arg ) > static_cast<typename promote_max_traits<Source, Target>::result>( std::numeric_limits<Target>::max() ) ) { throw numeric_cast_overflow(); } return static_cast<Target>(arg); } } // end of namespace internal //! A numeric cast which throws on overflow or underflow. template <typename Target, typename Source> inline Target numeric_cast( Source arg ) { typedef typename uiro::type::ct_if<std::numeric_limits<Source>::is_signed, typename internal::signed_tag, typename internal::unsigned_tag>::result tag; return internal::numeric_cast_helper<Target>( arg, tag() ); } } // end of namespace uiro
participants (1)
-
Dill, John