mirror of
				https://github.com/saitohirga/WSJT-X.git
				synced 2025-11-03 13:30:52 -05: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]
							 |