![]() |
![]() ![]() ![]() ![]() ![]() |
![]() |
Type Requirements and User-defined-types supportBoost , Chapter 1. Boost.NumericConversion , Chapter 1. Boost.NumericConversion
Как арифметические (встроенные), так и определяемые пользователем числовые типы требуют надлежащей специализации< Библиотека использует< Политика по умолчанию< using std::floor ; return floor(s); Поэтому для встроенных типов арифметики будут использоваться функции std. Определенные пользователем типы должны предоставлять перегруженные версии этих функций, чтобы использовать более круглые политики по умолчанию. Если эти перегрузки определены в зависимости от аргумента пространства имен пользователя, поиск (ADL) должен их найти, но если у вашего компилятора слабая ADL, вам может потребоваться поместить эти функции в другое место или написать свою собственную политику округления. По умолчанию< Conversion TraitsЕсли пользовательский определенный тип участвует в преобразовании, топредполагается, что UDT имеетболее широкий диапазон, чем любой встроенный тип, и, следовательно, значения некоторых<
< Range CheckingПоскольку определяемые пользователем числовые типы могут иметь особые диапазоны (например, неограниченный диапазон), эта библиотека не пытается предоставить значимую логику проверки диапазона, когда UDT участвуют в преобразовании. Поэтому, если ни Target, ни Source не являются встроенными типами, функция проверки диапазона< Существует два компонента класса< Когда и Target, и Source являются встроенными типами, класс преобразователя использует внутреннюю логику проверки диапазона, которая оптимизирована и настроена для комбинированных свойств типов. Однако эта внутренняя логика отключена, когда любой тип определен пользователем. В этом случае пользователь может указатьвнешнююполитику проверки диапазона, которая будет использоваться вместо внутреннего кода. См.numeric_cast_traitsдля подробной информации об использовании UDT с< Класс преобразователя выполняет фактическое преобразование с использованием политики Raw Converter. По умолчанию преобразователь просто выполняет< Однако, если UDT участвует,< Чтобы использовать UDT с< namespace boost { namespace numeric { template <typename Source> struct numeric_cast_traits<UDT, Source> { typedef conversion_traits<UDT, Source> conv_traits; //! The following are required: typedef YourOverflowHandlerPolicy overflow_policy; typedef YourRangeCheckerPolicy<conv_traits> range_checking_policy; typedef YourFloat2IntRounderPolicy<Source> rounding_policy; }; template <typename Target> struct numeric_cast_traits<Target, UDT> { typedef conversion_traits<Target, UDT> conv_traits; //! The following are required: typedef YourOverflowHandlerPolicy overflow_policy; typedef YourRangeCheckerPolicy<conv_traits> range_checking_policy; typedef YourFloat2IntRounderPolicy<UDT> rounding_policy; }; }}//namespace boost::numeric; Эти специализации уже определены с значениями по умолчанию для встроенных числовых типов. Отключить генерацию специализаций для встроенных типов можно, определив< Вот полный пример того, как определить пользовательский UDT для использования с< //! Define a simple custom number struct Double : boost::ordered_field_operators < Double , boost::ordered_field_operators2< Double, long double , boost::ordered_field_operators2< Double, double , boost::ordered_field_operators2< Double, float , boost::ordered_field_operators2< Double, int , boost::ordered_field_operators2< Double, unsigned int , boost::ordered_field_operators2< Double, long , boost::ordered_field_operators2< Double, unsigned long , boost::ordered_field_operators2< Double, long long , boost::ordered_field_operators2< Double, unsigned long long , boost::ordered_field_operators2< Double, char , boost::ordered_field_operators2< Double, unsigned char , boost::ordered_field_operators2< Double, short , boost::ordered_field_operators2< Double, unsigned short > > > > > > > > > > > > > > { Double() : v(0) {} template <typename T> explicit Double( T v ) : v(static_cast<double>(v)) {} template <typename T> Double& operator= ( T t ) { v = static_cast<double>(t); return *this; } bool operator < ( const Double& rhs ) const { return v < rhs.v; } template <typename T> bool operator < ( T rhs ) const { return v < static_cast<double>(rhs); } bool operator > ( const Double& rhs ) const { return v > rhs.v; } template <typename T> bool operator > ( T rhs ) const { return v > static_cast<double>(rhs); } bool operator ==( const Double& rhs ) const { return v == rhs.v; } template <typename T> bool operator == ( T rhs ) const { return v == static_cast<double>(rhs); } bool operator !() const { return v == 0; } Double operator -() const { return Double(-v); } Double& operator +=( const Double& t ) { v += t.v; return *this; } template <typename T> Double& operator +=( T t ) { v += static_cast<double>(t); return *this; } Double& operator -=( const Double& t ) { v -= t.v; return *this; } template <typename T> Double& operator -=( T t ) { v -= static_cast<double>(t); return *this; } Double& operator *= ( const Double& factor ) { v *= factor.v; return *this; } template <typename T> Double& operator *=( T t ) { v *= static_cast<double>(t); return *this; } Double& operator /= (const Double& divisor) { v /= divisor.v; return *this; } template <typename T> Double& operator /=( T t ) { v /= static_cast<double>(t); return (*this); } double v; }; //! Define numeric_limits for the custom type. namespace std { template<> class numeric_limits<Double> : public numeric_limits<double> { public: //! Limit our Double to a range of +/- 100.0 static Double (min)() { return Double(1.e-2); } static Double (max)() { return Double(1.e2); } static Double epsilon() { return Double( std::numeric_limits<double>::epsilon() ); } }; } //! Define range checking and overflow policies. namespace custom { //! Define a custom range checker template<typename Traits, typename OverFlowHandler> struct range_checker { typedef typename Traits::argument_type argument_type ; typedef typename Traits::source_type S; typedef typename Traits::target_type T; //! Check range of integral types. static boost::numeric::range_check_result out_of_range( argument_type s ) { using namespace boost::numeric; if( s > bounds<T>::highest() ) return cPosOverflow; else if( s < bounds<T>::lowest() ) return cNegOverflow; else return cInRange; } static void validate_range ( argument_type s ) { BOOST_STATIC_ASSERT( std::numeric_limits<T>::is_bounded ); OverFlowHandler()( out_of_range(s) ); } }; //! Overflow handler struct positive_overflow{}; struct negative_overflow{}; struct overflow_handler { void operator() ( boost::numeric::range_check_result r ) { using namespace boost::numeric; if( r == cNegOverflow ) throw negative_overflow() ; else if( r == cPosOverflow ) throw positive_overflow() ; } }; //! Define a rounding policy and specialize on the custom type. template<class S> struct Ceil : boost::numeric::Ceil<S>{}; template<> struct Ceil<Double> { typedef Double source_type; typedef Double const& argument_type; static source_type nearbyint ( argument_type s ) { #if !defined(BOOST_NO_STDC_NAMESPACE) using std::ceil ; #endif return Double( ceil(s.v) ); } typedef boost::mpl::integral_c< std::float_round_style, std::round_toward_infinity> round_style; }; //! Define a rounding policy and specialize on the custom type. template<class S> struct Trunc: boost::numeric::Trunc<S>{}; template<> struct Trunc<Double> { typedef Double source_type; typedef Double const& argument_type; static source_type nearbyint ( argument_type s ) { #if !defined(BOOST_NO_STDC_NAMESPACE) using std::floor; #endif return Double( floor(s.v) ); } typedef boost::mpl::integral_c< std::float_round_style, std::round_toward_zero> round_style; }; }//namespace custom; namespace boost { namespace numeric { //! Define the numeric_cast_traits specializations on the custom type. template <typename S> struct numeric_cast_traits<Double, S> { typedef custom::overflow_handler overflow_policy; typedef custom::range_checker < boost::numeric::conversion_traits<Double, S> , overflow_policy > range_checking_policy; typedef boost::numeric::Trunc<S> rounding_policy; }; template <typename T> struct numeric_cast_traits<T, Double> { typedef custom::overflow_handler overflow_policy; typedef custom::range_checker < boost::numeric::conversion_traits<T, Double> , overflow_policy > range_checking_policy; typedef custom::Trunc<Double> rounding_policy; }; //! Define the conversion from the custom type to built-in types and vice-versa. template<typename T> struct raw_converter< conversion_traits< T, Double > > { static T low_level_convert ( const Double& n ) { return static_cast<T>( n.v ); } }; template<typename S> struct raw_converter< conversion_traits< Double, S > > { static Double low_level_convert ( const S& n ) { return Double(n); } }; }}//namespace boost::numeric; Статья Type Requirements and User-defined-types support раздела Chapter 1. Boost.NumericConversion Chapter 1. Boost.NumericConversion может быть полезна для разработчиков на c++ и boost. Материалы статей собраны из открытых источников, владелец сайта не претендует на авторство. Там где авторство установить не удалось, материал подаётся без имени автора. В случае если Вы считаете, что Ваши права нарушены, пожалуйста, свяжитесь с владельцем сайта. :: Главная :: Chapter 1. Boost.NumericConversion ::
|
||||||||||||
©KANSoftWare (разработка программного обеспечения, создание программ, создание интерактивных сайтов), 2007 |