mirror of
				https://github.com/saitohirga/WSJT-X.git
				synced 2025-10-30 20:40:28 -04:00 
			
		
		
		
	
		
			
				
	
	
		
			154 lines
		
	
	
		
			5.0 KiB
		
	
	
	
		
			Plaintext
		
	
	
	
	
	
			
		
		
	
	
			154 lines
		
	
	
		
			5.0 KiB
		
	
	
	
		
			Plaintext
		
	
	
	
	
	
| [/
 | |
|     Boost.Optional
 | |
| 
 | |
|     Copyright (c) 2003-2007 Fernando Luis Cacciola Carballal
 | |
| 
 | |
|     Distributed under the Boost Software License, Version 1.0.
 | |
|     (See accompanying file LICENSE_1_0.txt or copy at
 | |
|     http://www.boost.org/LICENSE_1_0.txt)
 | |
| ]
 | |
| 
 | |
| [section  Improved numeric_cast<>]
 | |
| 
 | |
| [section Introduction]
 | |
| 
 | |
| The lack of preservation of range makes conversions between numeric types
 | |
| error prone. This is true for both implicit conversions and explicit
 | |
| conversions (through `static_cast`).
 | |
| [link boost_numericconversion.improved_numeric_cast__.numeric_cast `numeric_cast`]
 | |
| detects loss of range when a numeric type is converted, and throws an
 | |
| exception if the range cannot be preserved.
 | |
| 
 | |
| There are several situations where conversions are unsafe:
 | |
| 
 | |
| * Conversions from an integral type with a wider range than the target integral type.
 | |
| * Conversions from unsigned to signed (and vice versa) integral types.
 | |
| * Conversions from floating point types to integral types.
 | |
| 
 | |
| The C++ Standard does not specify the behavior when a numeric type is
 | |
| assigned a value that cannot be represented by the type, except for unsigned
 | |
| integral types \[3.9.1.4\], which must obey the laws of arithmetic modulo 2n
 | |
| (this implies that the result will be reduced modulo the number that is one
 | |
| greater than the largest value that can be represented). The fact that the
 | |
| behavior for overflow is undefined for all conversions (except the
 | |
| aforementioned unsigned to unsigned) makes any code that may produce
 | |
| positive or negative overflows exposed to portability issues.
 | |
| 
 | |
| By default `numeric_cast` adheres to the rules for implicit conversions mandated by
 | |
| the C++ Standard, such as truncating floating point types when converting
 | |
| to integral types. The implementation must guarantee that for a conversion
 | |
| to a type that can hold all possible values of the source type, there will
 | |
| be no runtime overhead.
 | |
| 
 | |
| [endsect]
 | |
| 
 | |
| [section numeric_cast]
 | |
|     
 | |
|     template <typename Target, typename Source> inline
 | |
|     Target numeric_cast( Source arg )
 | |
|     {
 | |
|         typedef conversion_traits<Target, Source>   conv_traits;
 | |
|         typedef numeric_cast_traits<Target, Source> cast_traits;
 | |
|         typedef converter
 | |
|             <
 | |
|                 Target,
 | |
|                 Source, 
 | |
|                 conv_traits,
 | |
|                 typename cast_traits::overflow_policy, 
 | |
|                 typename cast_traits::rounding_policy, 
 | |
|                 raw_converter<conv_traits>,
 | |
|                 typename cast_traits::range_checking_policy
 | |
|             > converter;
 | |
|         return converter::convert(arg);
 | |
|     }
 | |
| 
 | |
| `numeric_cast` returns the result of converting a value of type Source
 | |
| to a value of type Target. If out-of-range is detected, an overflow policy
 | |
| is executed whose default behavior is to throw an an exception (see 
 | |
| [link numeric_conversion_bad_numeric_cast bad_numeric_cast],
 | |
| [link numeric_conversion_negative_overflow negative_overflow] and
 | |
| [link numeric_conversion_possitive_overflow positive_overflow]
 | |
| ).
 | |
| 
 | |
| [endsect]
 | |
| 
 | |
| [section numeric_cast_traits]
 | |
| 
 | |
|     template <typename Target, typename Source, typename EnableIf = void>
 | |
|     struct numeric_cast_traits
 | |
|     {
 | |
|         typedef def_overflow_handler    overflow_policy;
 | |
|         typedef UseInternalRangeChecker range_checking_policy;
 | |
|         typedef Trunc<Source>           rounding_policy;
 | |
|     };
 | |
| 
 | |
| The behavior of `numeric_cast` may be tailored for custom numeric types through
 | |
| the specialization of `numeric_cast_traits`. (see 
 | |
| [link boost_numericconversion.type_requirements_and_user_defined_types_support User Defined Types] 
 | |
| for details.
 | |
| )
 | |
| 
 | |
| [endsect]
 | |
| 
 | |
| [section Examples]
 | |
| 
 | |
| The following example performs some typical conversions between numeric types:
 | |
| 
 | |
| #include <boost/numeric/conversion/cast.hpp>
 | |
| #include <iostream>
 | |
| 
 | |
|     int main()
 | |
|     {
 | |
|         using boost::numeric_cast;
 | |
| 
 | |
|         using boost::numeric::bad_numeric_cast;
 | |
|         using boost::numeric::positive_overflow;
 | |
|         using boost::numeric::negative_overflow;
 | |
| 
 | |
|         try
 | |
|         {
 | |
|             int i=42;
 | |
|             short s=numeric_cast<short>(i); // This conversion succeeds (is in range)
 | |
|         }
 | |
|         catch(negative_overflow& e) {
 | |
|             std::cout << e.what();
 | |
|         }
 | |
|         catch(positive_overflow& e) {
 | |
|             std::cout << e.what();
 | |
|         }
 | |
| 
 | |
|         try
 | |
|         {
 | |
|             float f=-42.1234;
 | |
| 
 | |
|             // This will cause a boost::numeric::negative_overflow exception to be thrown
 | |
|             unsigned int i=numeric_cast<unsigned int>(f);
 | |
|         }
 | |
|         catch(bad_numeric_cast& e) {
 | |
|             std::cout << e.what();
 | |
|         }
 | |
| 
 | |
|         double d= f + numeric_cast<double>(123); // int -> double
 | |
| 
 | |
|         unsigned long l=std::numeric_limits<unsigned long>::max();
 | |
| 
 | |
|         try
 | |
|         {
 | |
|             // This will cause a boost::numeric::positive_overflow exception to be thrown
 | |
|             // NOTE: *operations* on unsigned integral types cannot cause overflow
 | |
|             // but *conversions* to a signed type ARE range checked by numeric_cast.
 | |
| 
 | |
|             unsigned char c=numeric_cast<unsigned char>(l);
 | |
|         }
 | |
|         catch(positive_overflow& e) {
 | |
|             std::cout << e.what();
 | |
|         }
 | |
| 
 | |
| 
 | |
|         return 0;
 | |
|     }
 | |
| 
 | |
| [endsect]
 | |
| 
 | |
| [endsect]
 |