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] |