Используя метафункции MPL и шаблонные специализации для операций по композитным измерениям (определяется в<boost/units/dimension.hpp>), можно выполнить компиляцию арифметики времени в соответствии с правилами размерного анализа, описаннымивыше, для получения новых композитных измерений:
В качестве еще одной демонстрации гибкости системы мы заменяем тип значений<double>на тип значений<std::complex<double>>(игнорируя вопрос о значении сложных длин и энергий):
и найти, что код функционирует точно так, как ожидалось, без дополнительной работы, делегируя операции<std::complex<double>>и выполняя соответствующий размерный анализ:
Этот пример дает довольно обширный набор тестов, охватывающих большую часть.<quantity>Функциональность. Он использует систему единиц СИ, определенную в<boost/units/systems/si.hpp>.
Если мы определим несколько единиц и соответствующие величины,
/// scalarconstdoubles1=2;constlongx1=2;conststatic_rational<4,3>x2;/// define some unitsforceu1=newton;energyu2=joule;/// define some quantitiesquantity<force>q1(1.0*u1);quantity<energy>q2(2.0*u2);
Различные алгебраические операции между скалярами, единицами и величинами дают
S1:2X1:2X2:(4/3)U1:NU2:JQ1:1NQ2:2J
Скалярные/единичные операции:
U1*S1:2NS1*U1:2NU1/S1:0.5NS1/U1:2m^-1kg^-1s^2
Операции единицы/единицы и интегральные/рациональные полномочия единиц:
Допускается неявное преобразование между безразмерными величинами и их соответствующими типами значений:
/// check implicit unit conversion from dimensionless to value_type constdoubledimless=(q1/q1);
Можно определить общую функцию вычисления механической работы, которая принимает аргументы силы и расстояния в произвольной системе единиц и возвращает энергию в той же системе:
/// the physical definition of work - computed for an arbitrary unit system template<classSystem,classY>quantity<unit<energy_dimension,System>,Y>work(quantity<unit<force_dimension,System>,Y>F,quantity<unit<length_dimension,System>,Y>dx){returnF*dx;}
/// test calcuation of workquantity<force>F(1.0*newton);quantity<length>dx(1.0*meter);quantity<energy>E(work(F,dx));
которые функционируют так, как ожидается для величин СИ:
F=1Ndx=1mE=1J
Закон об идеальном газе также может быть реализован в единицах СИ:
/// the ideal gas law in si unitstemplate<classY>quantity<si::amount,Y>idealGasLaw(constquantity<si::pressure,Y>&P,constquantity<si::volume,Y>&V,constquantity<si::temperature,Y>&T){usingnamespaceboost::units::si;usingnamespaceconstants::codata;return(P*V/(R*T));}
/// test ideal gas lawquantity<temperature>T=(273.+37.)*kelvin;quantity<pressure>P=1.01325e5*pascals;quantity<length>r=0.5e-6*meters;quantity<volume>V=(4.0/3.0)*3.141592*pow<3>(r);quantity<amount>n(idealGasLaw(P,V,T));
Тригонометрические и обратные тригонометрические функции могут быть реализованы для любой модульной системы, обеспечивающей угловое базовое измерение. Для радианов эти функции встречаются в<boost/units/cmath.hpp>. Они ведут себя, как и ожидалось, с тригонометрическими функциями, принимающими угловую величину и возвращающими безразмерную величину, в то время как обратные тригонометрические функции берут безразмерную величину и возвращают угловую величину:
Определение нескольких угловых величин,
/// test trig stuffquantity<plane_angle>theta=0.375*radians;quantity<dimensionless>sin_theta=sin(theta);quantity<plane_angle>thetap=asin(sin_theta);
Определенные пользователем типы значений, которые поддерживают соответствующие арифметические операции, автоматически поддерживаются в качестве типов величин. Операторы, которые поддерживаются по умолчанию для типов количественных значений, являются унарными плюсами, унарными минусами, сложением, вычитанием, умножением, делением, равными, не равными, менее чем, менее или равными, более чем и более или равными. Поддержка рациональных сил и корней может быть добавлена перегрузкой классов<power_typeof_helper>и<root_typeof_helper>. Здесь мы реализуем класс, определяемый пользователем<measurement>, который моделирует численное измерение с соответствующей погрешностью измерения и соответствующей алгеброй и демонстрирует его использование в качестве типа величины; полный код находится вmeasurement.hpp.
Затем, определив некоторые<measurement><quantity>переменные
иллюстрирует неявное преобразование величин различных типов значений, где допускается неявное преобразование самих типов значений. N.B. Преобразование из двойного в int рассматривается как явное преобразование, потому что нет способа эмулировать точное поведение встроенного преобразования. Конструкторы допускают конверсию для двух случаев:
Этот пример демонстрирует использование<boost::math::quaternion>в качестве типа значения для<quantity>и обратного. Для первого случая мы сначала определяем специализации<power_typeof_helper>и<root_typeof_helper>для степеней и корней, соответственно:
/// specialize power typeof helpertemplate<classY,longN,longD>structpower_typeof_helper<boost::math::quaternion<Y>,static_rational<N,D>>{// boost::math::quaternion only supports integer powersBOOST_STATIC_ASSERT(D==1);typedefboost::math::quaternion<typenamepower_typeof_helper<Y,static_rational<N,D>>::type>type;statictypevalue(constboost::math::quaternion<Y>&x){returnboost::math::pow(x,static_cast<int>(N));}};
/// specialize root typeof helpertemplate<classY,longN,longD>structroot_typeof_helper<boost::math::quaternion<Y>,static_rational<N,D>>{// boost::math::quaternion only supports integer powersBOOST_STATIC_ASSERT(N==1);typedefboost::math::quaternion<typenameroot_typeof_helper<Y,static_rational<N,D>>::type>type;statictypevalue(constboost::math::quaternion<Y>&x){returnboost::math::pow(x,static_cast<int>(D));}};
Таким образом, все операции, определенные в классе<quaternion>, ведут себя правильно. Если бы для этого класса были определены рациональные силы, можно было бы вычислить рациональные силы и корни без каких-либо дополнительных изменений.
Здесь правильно функционируют унарные плюс-минус и операторы сложения и вычитания. К сожалению, операции умножения и деления терпят неудачу, потому что<quaternion>реализует их в терминах операторов<*=>и</=>соответственно, которые неспособны представлять гетерогенную единицу алгебры, необходимую для величин (идентичная проблема возникает с<std::complex<T>>, по той же причине). Чтобы вычислить рациональные силы и корни, нам нужно специализироваться<power_typeof_helper>и<root_typeof_helper>следующим образом:
/// specialize power typeof helper for quaternion<quantity<Unit,Y> >template<classUnit,longN,longD,classY>structpower_typeof_helper<boost::math::quaternion<quantity<Unit,Y>>,static_rational<N,D>>{typedeftypenamepower_typeof_helper<Y,static_rational<N,D>>::typevalue_type;typedeftypenamepower_typeof_helper<Unit,static_rational<N,D>>::typeunit_type;typedefquantity<unit_type,value_type>quantity_type;typedefboost::math::quaternion<quantity_type>type;statictypevalue(constboost::math::quaternion<quantity<Unit,Y>>&x){constboost::math::quaternion<value_type>tmp=pow<static_rational<N,D>>(boost::math::quaternion<Y>(x.R_component_1().value(),x.R_component_2().value(),x.R_component_3().value(),x.R_component_4().value()));returntype(quantity_type::from_value(tmp.R_component_1()),quantity_type::from_value(tmp.R_component_2()),quantity_type::from_value(tmp.R_component_3()),quantity_type::from_value(tmp.R_component_4()));}};
/// specialize root typeof helper for quaternion<quantity<Unit,Y> >template<classUnit,longN,longD,classY>structroot_typeof_helper<boost::math::quaternion<quantity<Unit,Y>>,static_rational<N,D>>{typedeftypenameroot_typeof_helper<Y,static_rational<N,D>>::typevalue_type;typedeftypenameroot_typeof_helper<Unit,static_rational<N,D>>::typeunit_type;typedefquantity<unit_type,value_type>quantity_type;typedefboost::math::quaternion<quantity_type>type;statictypevalue(constboost::math::quaternion<quantity<Unit,Y>>&x){constboost::math::quaternion<value_type>tmp=root<static_rational<N,D>>(boost::math::quaternion<Y>(x.R_component_1().value(),x.R_component_2().value(),x.R_component_3().value(),x.R_component_4().value()));returntype(quantity_type::from_value(tmp.R_component_1()),quantity_type::from_value(tmp.R_component_2()),quantity_type::from_value(tmp.R_component_3()),quantity_type::from_value(tmp.R_component_4()));}};
Этот пример показывает, как реализовать класс замены<complex>, который функционирует правильно как тип величины, так и класс контейнера количества, включая гетерогенные операции умножения и деления и рациональные силы и корни. Естественно, гетерогенные операции поддерживаются только на компиляторах, реализующих<typeof>. Основные различия заключаются в том, что двоичные операции не реализуются с использованием операторов<op=>и используют классы полезности<add_typeof_helper>,<subtract_typeof_helper>,<multiply_typeof_helper>и<divide_typeof_helper>. Кроме того,<power_typeof_helper>и<root_typeof_helper>определены для обоих случаев:
namespaceboost{namespaceunits{/// replacement complex class template<classT>classcomplex{public:typedefcomplex<T>this_type;complex(constT&r=0,constT&i=0):r_(r),i_(i){}complex(constthis_type&source):r_(source.r_),i_(source.i_){}this_type&operator=(constthis_type&source){if(this==&source)return*this;r_=source.r_;i_=source.i_;return*this;}T&real(){returnr_;}T&imag(){returni_;}constT&real()const{returnr_;}constT&imag()const{returni_;}this_type&operator+=(constT&val){r_+=val;return*this;}this_type&operator-=(constT&val){r_-=val;return*this;}this_type&operator*=(constT&val){r_*=val;i_*=val;return*this;}this_type&operator/=(constT&val){r_/=val;i_/=val;return*this;}this_type&operator+=(constthis_type&source){r_+=source.r_;i_+=source.i_;return*this;}this_type&operator-=(constthis_type&source){r_-=source.r_;i_-=source.i_;return*this;}this_type&operator*=(constthis_type&source){*this=*this*source;return*this;}this_type&operator/=(constthis_type&source){*this=*this/source;return*this;}private:Tr_,i_;};}}#ifBOOST_UNITS_HAS_BOOST_TYPEOF#includeBOOST_TYPEOF_INCREMENT_REGISTRATION_GROUP()BOOST_TYPEOF_REGISTER_TEMPLATE(boost::units::complex,1)#endifnamespaceboost{namespaceunits{template<classX>complex<typenameunary_plus_typeof_helper<X>::type>operator+(constcomplex<X>&x){typedeftypenameunary_plus_typeof_helper<X>::typetype;returncomplex<type>(x.real(),x.imag());}template<classX>complex<typenameunary_minus_typeof_helper<X>::type>operator-(constcomplex<X>&x){typedeftypenameunary_minus_typeof_helper<X>::typetype;returncomplex<type>(-x.real(),-x.imag());}template<classX,classY>complex<typenameadd_typeof_helper<X,Y>::type>operator+(constcomplex<X>&x,constcomplex<Y>&y){typedeftypenameboost::units::add_typeof_helper<X,Y>::typetype;returncomplex<type>(x.real()+y.real(),x.imag()+y.imag());}template<classX,classY>complex<typenameboost::units::subtract_typeof_helper<X,Y>::type>operator-(constcomplex<X>&x,constcomplex<Y>&y){typedeftypenameboost::units::subtract_typeof_helper<X,Y>::typetype;returncomplex<type>(x.real()-y.real(),x.imag()-y.imag());}template<classX,classY>complex<typenameboost::units::multiply_typeof_helper<X,Y>::type>operator*(constcomplex<X>&x,constcomplex<Y>&y){typedeftypenameboost::units::multiply_typeof_helper<X,Y>::typetype;returncomplex<type>(x.real()*y.real()-x.imag()*y.imag(),x.real()*y.imag()+x.imag()*y.real());// fully correct implementation has more complex return type//// typedef typename boost::units::multiply_typeof_helper<X,Y>::type xy_type;// // typedef typename boost::units::add_typeof_helper<// xy_type,xy_type>::type xy_plus_xy_type;// typedef typename// boost::units::subtract_typeof_helper<xy_type,xy_type>::type// xy_minus_xy_type;// // BOOST_STATIC_ASSERT((boost::is_same<xy_plus_xy_type,// xy_minus_xy_type>::value == true));// // return complex<xy_plus_xy_type>(x.real()*y.real()-x.imag()*y.imag(),// x.real()*y.imag()+x.imag()*y.real());}template<classX,classY>complex<typenameboost::units::divide_typeof_helper<X,Y>::type>operator/(constcomplex<X>&x,constcomplex<Y>&y){// naive implementation of complex divisiontypedeftypenameboost::units::divide_typeof_helper<X,Y>::typetype;returncomplex<type>((x.real()*y.real()+x.imag()*y.imag())/(y.real()*y.real()+y.imag()*y.imag()),(x.imag()*y.real()-x.real()*y.imag())/(y.real()*y.real()+y.imag()*y.imag()));// fully correct implementation has more complex return type//// typedef typename boost::units::multiply_typeof_helper<X,Y>::type xy_type;// typedef typename boost::units::multiply_typeof_helper<Y,Y>::type yy_type;//// typedef typename boost::units::add_typeof_helper<xy_type, xy_type>::type// xy_plus_xy_type;// typedef typename boost::units::subtract_typeof_helper<// xy_type,xy_type>::type xy_minus_xy_type;//// typedef typename boost::units::divide_typeof_helper<// xy_plus_xy_type,yy_type>::type xy_plus_xy_over_yy_type;// typedef typename boost::units::divide_typeof_helper<// xy_minus_xy_type,yy_type>::type xy_minus_xy_over_yy_type;//// BOOST_STATIC_ASSERT((boost::is_same<xy_plus_xy_over_yy_type,// xy_minus_xy_over_yy_type>::value == true));//// return complex<xy_plus_xy_over_yy_type>(// (x.real()*y.real()+x.imag()*y.imag())/// (y.real()*y.real()+y.imag()*y.imag()),// (x.imag()*y.real()-x.real()*y.imag())/// (y.real()*y.real()+y.imag()*y.imag()));}template<classY>complex<Y>pow(constcomplex<Y>&x,constY&y){std::complex<Y>tmp(x.real(),x.imag());tmp=std::pow(tmp,y);returncomplex<Y>(tmp.real(),tmp.imag());}template<classY>std::ostream&operator<<(std::ostream&os,constcomplex<Y>&val){os<<val.real()<<" + "<<val.imag()<<" i";returnos;}/// specialize power typeof helper for complex<Y>template<classY,longN,longD>structpower_typeof_helper<complex<Y>,static_rational<N,D>>{typedefcomplex<typenamepower_typeof_helper<Y,static_rational<N,D>>::type>type;statictypevalue(constcomplex<Y>&x){conststatic_rational<N,D>rat;constYm=Y(rat.numerator())/Y(rat.denominator());returnboost::units::pow(x,m);}};/// specialize root typeof helper for complex<Y>template<classY,longN,longD>structroot_typeof_helper<complex<Y>,static_rational<N,D>>{typedefcomplex<typenameroot_typeof_helper<Y,static_rational<N,D>>::type>type;statictypevalue(constcomplex<Y>&x){conststatic_rational<N,D>rat;constYm=Y(rat.denominator())/Y(rat.numerator());returnboost::units::pow(x,m);}};/// specialize power typeof helper for complex<quantity<Unit,Y> >template<classY,classUnit,longN,longD>structpower_typeof_helper<complex<quantity<Unit,Y>>,static_rational<N,D>>{typedeftypenamepower_typeof_helper<Y,static_rational<N,D>>::typevalue_type;typedeftypenamepower_typeof_helper<Unit,static_rational<N,D>>::typeunit_type;typedefquantity<unit_type,value_type>quantity_type;typedefcomplex<quantity_type>type;statictypevalue(constcomplex<quantity<Unit,Y>>&x){constcomplex<value_type>tmp=pow<static_rational<N,D>>(complex<Y>(x.real().value(),x.imag().value()));returntype(quantity_type::from_value(tmp.real()),quantity_type::from_value(tmp.imag()));}};/// specialize root typeof helper for complex<quantity<Unit,Y> >template<classY,classUnit,longN,longD>structroot_typeof_helper<complex<quantity<Unit,Y>>,static_rational<N,D>>{typedeftypenameroot_typeof_helper<Y,static_rational<N,D>>::typevalue_type;typedeftypenameroot_typeof_helper<Unit,static_rational<N,D>>::typeunit_type;typedefquantity<unit_type,value_type>quantity_type;typedefcomplex<quantity_type>type;statictypevalue(constcomplex<quantity<Unit,Y>>&x){constcomplex<value_type>tmp=root<static_rational<N,D>>(complex<Y>(x.real().value(),x.imag().value()));returntype(quantity_type::from_value(tmp.real()),quantity_type::from_value(tmp.imag()));}};}// namespace units}// namespace boost
С этим классом замены<complex>мы можем объявить сложную переменную:
Этот пример обеспечивает специальный тест производительности для проверки того, что нулевые накладные расходы на время выполнения возникают при использовании<quantity>вместо<double>. Обратите внимание, что оптимизация производительности и тестирование не тривиальны, поэтому в профилировании необходимо соблюдать определенную осторожность. Также важно иметь компилятор, способный эффективно оптимизировать множество инстанциаций шаблонов и встроенных вызовов для достижения максимальной производительности. Нулевые накладные расходы для этого теста были проверены с использованием gcc 4.0.1 и icc 9.0, 10.0 и 10.1 на Mac OS 10.4 и 10.5 и с использованием msvc 8.0 на Windows XP.
Этот пример демонстрирует реализацию двух не-СИ единиц длины, морской мили:
namespacenautical{structlength_base_unit:boost::units::base_unit<length_base_unit,length_dimension,1>{staticstd::stringname(){return"nautical mile";}staticstd::stringsymbol(){return"nmi";}};typedefboost::units::make_system<length_base_unit>::typesystem;/// unit typedefstypedefunit<length_dimension,system>length;staticconstlengthmile,miles;}// namespace nautical// helper for conversions between nautical length and si lengthBOOST_UNITS_DEFINE_CONVERSION_FACTOR(nautical::length_base_unit,boost::units::si::meter_base_unit,double,1.852e3);
Имперская нога :
namespaceimperial{structlength_base_unit:boost::units::base_unit<length_base_unit,length_dimension,2>{staticstd::stringname(){return"foot";}staticstd::stringsymbol(){return"ft";}};typedefboost::units::make_system<length_base_unit>::typesystem;/// unit typedefstypedefunit<length_dimension,system>length;staticconstlengthfoot,feet;}// imperial// helper for conversions between imperial length and si lengthBOOST_UNITS_DEFINE_CONVERSION_FACTOR(imperial::length_base_unit,boost::units::si::meter_base_unit,double,1.0/3.28083989501312);
Эти единицы включают преобразования между собой и счетчиком. Определены три функции для вычисления высоты радиолокационного луча с радиолокационной дальности и локального радиуса Земли. Первый берет аргументы в одной системе и возвращает значение в той же системе:
Второй тип аналогичен, но шаблонируется по типу возврата, так что аргументы преобразуются в систему возврата внутри:
template<classreturn_type,classSystem1,classSystem2,typenameT>return_typeradar_beam_height(constquantity<unit<length_dimension,System1>,T>&radar_range,constquantity<unit<length_dimension,System2>,T>&earth_radius,Tk=4.0/3.0){// need to decide which system to use for calculationconstreturn_typerr(radar_range),er(earth_radius);returnreturn_type(pow<2>(rr)/(2.0*k*er));}
Наконец, третья функция является эмпирическим приближением, которое действует только для радиолокационных диапазонов, указанных в морских милях, возвращая высоту луча в футах. Эта функция использует разнородную единицу морских миль на квадратный корень футов для обеспечения правильности размеров:
Этот пример демонстрирует использование абсолютных температур и относительных температурных различий в Фаренгейте и преобразование между ними и температурной шкалой Кельвина. Этот вопрос затрагивает некоторые удивительно глубокие математические понятия (см.Википедиядля базового обзора), но для наших целей здесь мы просто заметим, что важно уметь различать абсолютное измерение температуры и измерение разности температур. Это достигается с помощью.<absolute>Оберточный класс.
Сначала мы определим систему, используя предварительно заданный базовый блок по Фаренгейту:
Начало. Библиотека единиц не требует, чтобы коэффициенты преобразования составляли постоянные времени, как показано в этом примере:
usingboost::units::base_dimension;usingboost::units::base_unit;staticconstlongcurrency_base=1;structcurrency_base_dimension:base_dimension<currency_base_dimension,1>{};typedefcurrency_base_dimension::dimension_typecurrency_type;template<longN>structcurrency_base_unit:base_unit<currency_base_unit<N>,currency_type,currency_base+N>{};typedefcurrency_base_unit<0>us_dollar_base_unit;typedefcurrency_base_unit<1>euro_base_unit;typedefus_dollar_base_unit::unit_typeus_dollar;typedefeuro_base_unit::unit_typeeuro;// an array of all possible conversionsdoubleconversion_factors[2][2]={{1.0,1.0},{1.0,1.0}};doubleget_conversion_factor(longfrom,longto){return(conversion_factors[from][to]);}voidset_conversion_factor(longfrom,longto,doublevalue){conversion_factors[from][to]=value;conversion_factors[to][from]=1.0/value;}BOOST_UNITS_DEFINE_CONVERSION_FACTOR_TEMPLATE((longN1)(longN2),currency_base_unit<N1>,currency_base_unit<N2>,double,get_conversion_factor(N1,N2));
В этом случае любой блок, который сводится к перегруженному блоку, будет выводиться с помощью символа замены.
Специальные названия и символы для систем SI и CGS встречаются в<boost/units/systems/si/io.hpp>и<boost/units/systems/cgs/io.hpp>соответственно. Если эти заголовки не включены, выход будет просто следовать правилам по умолчанию, используя соответствующие фундаментальные размеры. Обратите внимание, что ни одна из этих функций не определена для величин, поскольку для этого потребуется сделать предположения о том, как следует форматировать соответствующий тип значений.
Для удобства предусмотрены три форматтера<ostream>,<symbol_format>,<name_format>и<typename_format>. Они выбирают текстовое представление блоков, предоставленное<symbol_string>или<name_string>в первых двух случаях, в то время как последний возвращает распутанное имя типа для целей отладки. Форматирование масштабируемой единицы также выполняется правильно.
Очень часто бывает так, что требуется.<unit>автоматически, в зависимости от его значения, удерживать составную часть в ограниченном диапазоне, обычно между 1 и 999.
usingboost::units::binary_prefix;usingboost::units::engineering_prefix;usingboost::units::no_prefix;quantity<length>l=2.345*meters;// A quantity of length, in units of meters.cout<<engineering_prefix<<l<<endl;// Outputs "2.345 m".l=1000.0*l;// Increase it by 1000, so expect a k prefix.// Note that a double 1000.0 is required - an integer will fail to compile.cout<<engineering_prefix<<l<<endl;// Output autoprefixed with k to "2.345 km".quantity<energy>e=kilograms*pow<2>(l/seconds);// A quantity of energy.cout<<engineering_prefix<<e<<endl;// 5.49902 MJcout<<name_format<<engineering_prefix<<e<<endl;// 5.49902 megaJoule
(Полный наборинженерных и научных мультипликаторовне используется (например, не цент или деци), а только мощности десяти, которые кратны трем, 103).
Аналогично, эквивалентныедвоичные префиксыиспользуются для отображения вычислительных килобайт, мегабайт, гигабайт...
Эта шкала указана в IEC 60027-2, Второе издание, 2000-11, Буквенные символы для использования в электротехнике - Часть 2: Телекоммуникации и электроника.
// Don't forget that the units name or symbol format specification is persistent.cout<<symbol_format<<endl;// Resets the format to the default symbol format.quantity<byte_base_unit::unit_type>b=2048.*byte_base_unit::unit_type();cout<<engineering_prefix<<b<<endl;// 2.048 kbcout<<symbol_format<<binary_prefix<<b<<endl;// "2 Kib"
Но обратите внимание, что скалярные безразмерные значения, такие как int, float и double, являются, а не, автоматически префиксируемыми манипуляторами iostream.
Вы можете вывести имя или символ единицы (а не наиболее распространенное количество единицы).
constlengthL;// A unit of length (but not a quantity of length).cout<<L<<endl;// Default length unit is meter,// but default is symbol format so output is just "m".cout<<name_format<<L<<endl;// default length name is "meter".
Также обратите внимание, что все флаги форматирования являются постоянными, так что если вы установите Engineering_prefix, то это относится ко всем будущим выводам, пока вы не выберете binary_prefix или явно не выключите автопрефикс. Вы можете указать отсутствие префикса (конечно, по умолчанию) двумя способами:
no_prefix(cout);// Clear any prefix flag.cout<<no_prefix<<endl;// Clear any prefix flag using `no_prefix` manipulator.
И вы можете получить флаги формата для диагностики проблем.
cout<<boost::units::get_autoprefix(cout)<<endl;// 8 is `autoprefix_binary` from `enum autoprefix_mode`.cout<<boost::units::get_format(cout)<<endl;// 1 is `name_fmt` from `enum format_mode`.
Этот пример показывает, как реализовать интерфейс, который позволяет использовать различные блоки во время выполнения, сохраняя при этом безопасность типа для внутренних вычислений.
namespace{usingnamespaceboost::units;usingimperial::foot_base_unit;std::map<std::string,quantity<si::length>>known_units;}quantity<si::length>calculate(constquantity<si::length>&t){return(boost::units::hypot(t,2.0*si::meters));}intmain(){known_units["meter"]=1.0*si::meters;known_units["centimeter"]=.01*si::meters;known_units["foot"]=conversion_factor(foot_base_unit::unit_type(),si::meter)*si::meter;std::stringoutput_type("meter");std::stringinput;while((std::cout<<"> ")&&(std::cin>>input)){if(!input.empty()&&input[0]=='#'){std::getline(std::cin,input);}elseif(input=="exit"){break;}elseif(input=="help"){std::cout<<"type \"exit\" to exit\n""type \"return 'unit'\" to set the return units\n""type \"'number' 'unit'\" to do a simple calculation"<<std::endl;}elseif(input=="return"){if(std::cin>>input){if(known_units.find(input)!=known_units.end()){output_type=input;std::cout<<"Done."<<std::endl;}else{std::cout<<"Unknown unit \""<<input<<"\""<<std::endl;}}else{break;}}else{try{doublevalue=boost::lexical_cast<double>(input);if(std::cin>>input){if(known_units.find(input)!=known_units.end()){std::cout<<static_cast<double>(calculate(value*known_units[input])/known_units[output_type])<<' '<<output_type<<std::endl;}else{std::cout<<"Unknown unit \""<<input<<"\""<<std::endl;}}else{break;}}catch(...){std::cout<<"Input error"<<std::endl;}}}}
Заголовок<boost/units/lambda.hpp>обеспечивает перегрузки и специализацию, необходимые для создания Boost. Объединяется с Boost. Библиотека Ламбда.
intmain(intargc,char**argv){usingnamespacestd;namespacebl=boost::lambda;namespacebu=boost::units;namespacesi=boost::units::si;////////////////////////////////////////////////////////////////////////// Mechanical example: linear accelerated movement////////////////////////////////////////////////////////////////////////// Initial condition variables for acceleration, speed, and displacementbu::quantity<si::acceleration>a=2.0*si::meters_per_second_squared;bu::quantity<si::velocity>v=1.0*si::meters_per_second;bu::quantity<si::length>s0=0.5*si::meter;// Displacement over timeboost::function<bu::quantity<si::length>(bu::quantity<si::time>)>s=0.5*bl::var(a)*bl::_1*bl::_1+bl::var(v)*bl::_1+bl::var(s0);cout<<"Linear accelerated movement:"<<endl<<"a = "<<a<<", v = "<<v<<", s0 = "<<s0<<endl<<"s(1.0 * si::second) = "<<s(1.0*si::second)<<endl<<endl;// Change initial conditionsa=1.0*si::meters_per_second_squared;v=2.0*si::meters_per_second;s0=-1.5*si::meter;cout<<"a = "<<a<<", v = "<<v<<", s0 = "<<s0<<endl<<"s(1.0 * si::second) = "<<s(1.0*si::second)<<endl<<endl;////////////////////////////////////////////////////////////////////////// Electrical example: oscillating current////////////////////////////////////////////////////////////////////////// Constants for the current amplitude, frequency, and offset currentconstbu::quantity<si::current>iamp=1.5*si::ampere;constbu::quantity<si::frequency>f=1.0e3*si::hertz;constbu::quantity<si::current>i0=0.5*si::ampere;// The invocation of the sin function needs to be postponed using// bind to specify the oscillation function. A lengthy static_cast// to the function pointer referencing boost::units::sin() is needed// to avoid an "unresolved overloaded function type" error.boost::function<bu::quantity<si::current>(bu::quantity<si::time>)>i=iamp*bl::bind(static_cast<bu::dimensionless_quantity<si::system,double>::type(*)(constbu::quantity<si::plane_angle>&)>(bu::sin),2.0*pi*si::radian*f*bl::_1)+i0;cout<<"Oscillating current:"<<endl<<"iamp = "<<iamp<<", f = "<<f<<", i0 = "<<i0<<endl<<"i(1.25e-3 * si::second) = "<<i(1.25e-3*si::second)<<endl<<endl;////////////////////////////////////////////////////////////////////////// Geometric example: area calculation for a square////////////////////////////////////////////////////////////////////////// Length constantconstbu::quantity<si::length>l=1.5*si::meter;// Again an ugly static_cast is needed to bind pow<2> to the first// function argument.boost::function<bu::quantity<si::area>(bu::quantity<si::length>)>A=bl::bind(static_cast<bu::quantity<si::area>(*)(constbu::quantity<si::length>&)>(bu::pow<2>),bl::_1);cout<<"Area of a square:"<<endl<<"A("<<l<<") = "<<A(l)<<endl<<endl;////////////////////////////////////////////////////////////////////////// Thermal example: temperature difference of two absolute temperatures////////////////////////////////////////////////////////////////////////// Absolute temperature constantsconstbu::quantity<bu::absolute<si::temperature>>Tref=273.15*bu::absolute<si::temperature>();constbu::quantity<bu::absolute<si::temperature>>Tamb=300.00*bu::absolute<si::temperature>();boost::function<bu::quantity<si::temperature>(bu::quantity<bu::absolute<si::temperature>>,bu::quantity<bu::absolute<si::temperature>>)>dT=bl::_2-bl::_1;cout<<"Temperature difference of two absolute temperatures:"<<endl<<"dT("<<Tref<<", "<<Tamb<<") = "<<dT(Tref,Tamb)<<endl<<endl;return0;}
Статья Examples раздела The Boost C++ Libraries BoostBook Documentation Subset Chapter 40. Boost.Units 1.1.0 может быть полезна для разработчиков на c++ и boost.
Материалы статей собраны из открытых источников, владелец сайта не претендует на авторство. Там где авторство установить не удалось, материал подаётся без имени автора. В случае если Вы считаете, что Ваши права нарушены, пожалуйста, свяжитесь с владельцем сайта.