Boost C++ Libraries Home Libraries People FAQ More

PrevUpHomeNext

Examples

Dimension Example
Unit Example
Quantity Example
Kitchen Sink Example
Conversion Example
User Defined Types
Complex Example
Performance Example
Radar Beam Height
Heterogeneous Unit Example
Absolute and Relative Temperature Example
Runtime Conversion Factor Example
Units with Non-base Dimensions
Output for Composite Units
Conversion Factor
Runtime Units
Interoperability with Boost.Lambda

(dimension.cpp)

By using MPL metafunctions and the template specializations for operations on composite dimensions (defined in boost/units/dimension.hpp) it is possible to perform compile time arithmetic according to the dimensional analysis rules described above to produce new composite dimensions :
在復合量綱(composite dimension)(定義於boost/units/dimension.hpp文件)基礎上通過MPL元函數(metafunction)和模板特化(template specialization)按照之前介紹的量綱分析法則(dimensional analysis rules)執行編譯時運算(perform compile time arithmetic)得到新的復合量綱(composite dimension):

typedef mpl::times<length_dimension,mass_dimension>::type   LM_type;
typedef mpl::divides<length_dimension,time_dimension>::type L_T_type;
typedef static_root<
    mpl::divides<energy_dimension,mass_dimension>::type,
    static_rational<2>
>::type    V_type;

outputting (with symbol demangling, implemented in boost/units/detail/utility.hpp)
通過在boost/units/detail/utility.hpp中實現的符號重整(symbol demangling)後輸出(下面的數字11、21應該是1、2,原文應該錯了,譯者注)

length_dimension  = list<dim<length_base_dimension, static_rational<1l, 1l> >, dimensionless_type>
mass_dimension    = list<dim<mass_base_dimension, static_rational<1l, 1l> >, dimensionless_type>
time_dimension    = list<dim<time_base_dimension, static_rational<1l, 1l> >, dimensionless_type>
energy_dimension  = list<dim<length_base_dimension, static_rational<2l, 1l> >, list<dim<mass_base_dimension, static_rational<1l, 1l> >, list<dim<time_base_dimension, static_rational<-2l, 1l> >, dimensionless_type> > >
LM_type      = list<dim<length_base_dimension, static_rational<1l, 1l> >, list<dim<mass_base_dimension, static_rational<1l, 1l> >, dimensionless_type> >
L_T_type     = list<dim<length_base_dimension, static_rational<1l, 1l> >, list<dim<time_base_dimension, static_rational<-1l, 1l> >, dimensionless_type> >
V_type       = list<dim<length_base_dimension, static_rational<1l, 1l> >, list<dim<time_base_dimension, static_rational<-1l, 1l> >, dimensionless_type> >

(unit.cpp)

This example demonstrates the use of the simple but functional unit system implemented in libs/units/example/test_system.hpp :
這個例子展示了一個簡單但實用的單位系統,在libs/units/example/test_system.hpp文件中實現:

const length                    L;
const mass                      M;
// needs to be namespace-qualified because of global time definition
const boost::units::test::time  T;
const energy                    E;

We can perform various algebraic operations on these units, resulting in the following output:
我們可以在這些單位上執行很多代數運算,輸出如下:

L             = m
L+L           = m
L-L           = m
L/L           = dimensionless 
meter*meter   = m^2
M*(L/T)*(L/T) = m^2 kg s^-2
M*(L/T)^2     = m^2 kg s^-2
L^3           = m^3
L^(3/2)       = m^(3/2)
2vM           = kg^(1/2)
(3/2)vM       = kg^(2/3)

(quantity.cpp)

This example demonstrates how to use quantities of our toy unit system :
這個例子展示了如何在我們的單位系統(unit system)上使用數量(quantity):

quantity<length> L = 2.0*meters;                     // quantity of length
quantity<energy> E = kilograms*pow<2>(L/seconds);    // quantity of energy

giving us the basic quantity functionality :
會有最基本的數量(quantity)的功能:

L                                 = 2 m
L+L                               = 4 m
L-L                               = 0 m
L*L                               = 4 m^2
L/L                               = 1 dimensionless 
L*meter                           = 2 m^2
kilograms*(L/seconds)*(L/seconds) = 4 m^2 kg s^-2
kilograms*(L/seconds)^2           = 4 m^2 kg s^-2
L^3                               = 8 m^3
L^(3/2)                           = 2.82843 m^(3/2)
2vL                               = 1.41421 m^(1/2)
(3/2)vL                           = 1.5874 m^(2/3)

As a further demonstration of the flexibility of the system, we replace the double value type with a std::complex<double> value type (ignoring the question of the meaningfulness of complex lengths and energies) :
為了進一步展示系統的適應性(flexibility),我們把數值類型(value type)從double換成std::complex<double>(請無視長度和能量的複數含義):

quantity<length,std::complex<double> > L(std::complex<double>(3.0,4.0)*meters);
quantity<energy,std::complex<double> > E(kilograms*pow<2>(L/seconds));

and find that the code functions exactly as expected with no additional work, delegating operations to std::complex<double> and performing the appropriate dimensional analysis :
這些代碼只是把操作符轉發給std::complex<double>類並執行了適當的量綱分析:

L                                 = (3,4) m
L+L                               = (6,8) m
L-L                               = (0,0) m
L*L                               = (-7,24) m^2
L/L                               = (1,0) dimensionless 
L*meter                           = (3,4) m^2
kilograms*(L/seconds)*(L/seconds) = (-7,24) m^2 kg s^-2
kilograms*(L/seconds)^2           = (-7,24) m^2 kg s^-2
L^3                               = (-117,44) m^3
L^(3/2)                           = (2,11) m^(3/2)
2vL                               = (2,1) m^(1/2)
(3/2)vL                           = (2.38285,1.69466) m^(2/3)

(kitchen_sink.cpp)

This example provides a fairly extensive set of tests covering most of the quantity functionality. It uses the SI unit system defined in boost/units/systems/si.hpp.
這個例子為quantity的功能提供了一個比較全面的測試,使用定義在boost/units/systems/si.hpp文件中的SI單位系統。

If we define a few units and associated quantities,
我們定義幾個單位(unit)和數量(quantity),

/// scalar
const double    s1 = 2;

const long                  x1 = 2;
const static_rational<4,3>  x2;

/// define some units
force       u1 = newton;
energy      u2 = joule;

/// define some quantities
quantity<force>      q1(1.0*u1);
quantity<energy>     q2(2.0*u2);

the various algebraic operations between scalars, units, and quantities give
這幾個標量、單位和數量之間的代數運算結果是

S1 :    2
X1 :    2
X2 :    (4/3)
U1 :    N
U2 :    J
Q1 :    1 N
Q2 :    2 J

Scalar/unit operations :
標量和單位之間的運算:

U1*S1 : 2 N
S1*U1 : 2 N
U1/S1 : 0.5 N
S1/U1 : 2 m^-1 kg^-1 s^2

Unit/unit operations and integral/rational powers of units :
單位和單位之間的運算以及單位的整數/有理數乘方:

U1+U1 : N
U1-U1 : N
U1*U1 : m^2 kg^2 s^-4
U1/U1 : dimensionless
U1*U2 : m^3 kg^2 s^-4
U1/U2 : m^-1
U1^X  : m^2 kg^2 s^-4
X1vU1 : m^(1/2) kg^(1/2) s^-1
U1^X2 : m^(4/3) kg^(4/3) s^(-8/3)
X2vU1 : m^(3/4) kg^(3/4) s^(-3/2)

Scalar/quantity operations :
標量和數量之間的運算:

Q1*S1 : 2 N
S1*Q1 : 2 N
Q1/S1 : 0.5 N
S1/Q1 : 2 m^-1 kg^-1 s^2

Unit/quantity operations :
單位和數量之間的運算:

U1*Q1 : 1 m^2 kg^2 s^-4
Q1*U1 : 1 m^2 kg^2 s^-4
U1/Q1 : 1 dimensionless
Q1/U1 : 1 dimensionless

Quantity/quantity operations and integral/rational powers of quantities :
數量和數量之間的運算以及數量的整數/有理數次乘方:

+Q1   : 1 N
-Q1   : -1 N
Q1+Q1 : 2 N
Q1-Q1 : 0 N
Q1*Q1 : 1 m^2 kg^2 s^-4
Q1/Q1 : 1 dimensionless
Q1*Q2 : 2 m^3 kg^2 s^-4
Q1/Q2 : 0.5 m^-1
Q1^X1 : 1 m^2 kg^2 s^-4
X1vQ1 : 1 m^(1/2) kg^(1/2) s^-1
Q1^X2 : 1 m^(4/3) kg^(4/3) s^(-8/3)
X2vQ1 : 1 m^(3/4) kg^(3/4) s^(-3/2)

Logical comparison operators are also defined between quantities :
數量之間同樣定義了邏輯比較運算:

/// check comparison tests
quantity<length>    l1(1.0*meter),
                    l2(2.0*meters);

giving

l1 == l2    false
l1 != l2    true
l1 <= l2    true
l1 < l2     true
l1 >= l2    false
l1 > l2     false

Implicit conversion is allowed between dimensionless quantities and their corresponding value types :
無量綱數量和其數值類型之間可以隱式轉換:

/// check implicit unit conversion from dimensionless to value_type  
const double    dimless = (q1/q1);

A generic function for computing mechanical work can be defined that takes force and distance arguments in an arbitrary unit system and returns energy in the same system:
下面這個計算機械功的泛型函數接受任意單位系統的力和距離作為參數並返回相同系統的功:

/// the physical definition of work - computed for an arbitrary unit system 
template<class System,class Y>
quantity<unit<energy_dimension,System>,Y> 
work(quantity<unit<force_dimension,System>,Y> F,
     quantity<unit<length_dimension,System>,Y> dx)
{
    return F*dx;
}

/// test calcuation of work
quantity<force>       F(1.0*newton);
quantity<length>      dx(1.0*meter);
quantity<energy>      E(work(F,dx));

which functions as expected for SI quantities :
對於SI數量函數工作正確:

F  = 1 N
dx = 1 m
E  = 1 J

The ideal gas law can also be implemented in SI units :
理想氣體定律同樣可以用SI單位實現:

/// the ideal gas law in si units
template<class Y>
quantity<si::amount,Y> 
idealGasLaw(const quantity<si::pressure,Y>& P,
            const quantity<si::volume,Y>& V,
            const quantity<si::temperature,Y>& T)
{
    using namespace boost::units::si;
    
    #if BOOST_UNITS_HAS_TYPEOF 
    using namespace constants::codata;
    return (P*V/(R*T));
    #else
    return P*V/(8.314472*(joules/(kelvin*mole))*T);
    #endif // BOOST_UNITS_HAS_TYPEOF
}

/// test ideal gas law
quantity<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));

with the resulting output :

r = 5e-07 m
P = 101325 Pa
V = 5.23599e-19 m^3
T = 310 K
n = 2.05835e-17 mol
R = 8.314472 m^2 kg s^-2 K^-1 mol^-1 (rel. unc. = 1.8e-06)

Trigonometric and inverse trigonometric functions can be implemented for any unit system that provides an angular base dimension. For radians, these functions are found in boost/units/cmath.hpp These behave as one expects, with trigonometric functions taking an angular quantity and returning a dimensionless quantity, while the inverse trigonometric functions take a dimensionless quantity and return an angular quantity :
三角函數和反三角函數也能在任意提供角度基礎量綱的單位系統上實現。 對於弧度,這些函數定義在boost/units/cmath.hpp。 這些函數就像你想的那樣,三角函數以弧度數量為參數返回一個無量綱數量,反三角函數以無量綱數量為參數返回一個弧度數量:

Defining a few angular quantities,
定義幾個弧度數量,

/// test trig stuff
quantity<plane_angle>           theta = 0.375*radians;
quantity<dimensionless>         sin_theta = sin(theta);
quantity<plane_angle>           thetap = asin(sin_theta);

yields

theta            = 0.375 rd
sin(theta)       = 0.366273 dimensionless
asin(sin(theta)) = 0.375 rd

Dealing with complex quantities is trivial. Here is the calculation of complex impedance :
複數的數量也是一樣的。下面就是複數電阻的計算:

quantity<electric_potential,complex_type> v = complex_type(12.5,0.0)*volts;
quantity<current,complex_type>            i = complex_type(3.0,4.0)*amperes;
quantity<resistance,complex_type>         z = complex_type(1.5,-2.0)*ohms;

giving

V   = (12.5,0) V
I   = (3,4) A
Z   = (1.5,-2) Ohm
I*Z = (12.5,0) V

User-defined value types that support the appropriate arithmetic operations are automatically supported as quantity value types. The operators that are supported by default for quantity value types are unary plus, unary minus, addition, subtraction, multiplication, division, equal-to, not-equal-to, less-than, less-or-equal-to, greater-than, and greater-or-equal-to. Support for rational powers and roots can be added by overloading the power_typeof_helper and root_typeof_helper classes. Here we implement a user-defined measurement class that models a numerical measurement with an associated measurement error and the appropriate algebra and demonstrates its use as a quantity value type; the full code is found in measurement.hpp.
用戶自定義的數值類型如果支持這些算術運算,就可以自動地支持數量的運算。 數量的數值類型默認支持的運算有:取正、取負、加、減、乘、除、等於、不等於、小於、小於等於、大於和大於等於。 支持有理數次乘方開方可以通過添加power_typeofo_helperroot_typeof_helper類的特化(原文為overload,但應該是特化,而不是重載,譯者注)來實現。 我們定義一個類measurement表示數字的度量(numerical measurement),相關的度量錯誤和適當的代數運算,將它作為數量(quantity)的數值類型(value type);完整的代碼請見measurement.hpp

Then, defining some measurement quantity variables

quantity<length,measurement<double> >
    u(measurement<double>(1.0,0.0)*meters),
    w(measurement<double>(4.52,0.02)*meters),
    x(measurement<double>(2.0,0.2)*meters),
    y(measurement<double>(3.0,0.6)*meters);

gives

x+y-w         = 0.48(+/-0.632772) m
w*x           = 9.04(+/-0.904885) m^2
x/y           = 0.666667(+/-0.149071) dimensionless

If we implement the overloaded helper classes for rational powers and roots then we can also compute rational powers of measurement quantities :
如果我們特化(overload,譯者注)了乘方和開方的helper classes,就可以計算measurement數量的乘方了:

w*y^2/(u*x)^2 = 10.17(+/-3.52328) m^-1
w/(u*x)^(1/2) = 3.19612(+/-0.160431) dimensionless

(conversion.cpp)

This example demonstrates the various allowed conversions between SI and CGS units. Defining some quantities
這個例子展示了SI和CGS單位之間的轉換。先定義幾個數量

quantity<si::length>     L1 = quantity<si::length,int>(int(2.5)*si::meters);
quantity<si::length,int> L2(quantity<si::length,double>(2.5*si::meters));

illustrates implicit conversion of quantities of different value types where implicit conversion of the value types themselves is allowed. N.B. The conversion from double to int is treated as an explicit conversion because there is no way to emulate the exact behavior of the built-in conversion. Explicit constructors allow conversions for two cases:
舉例說明了當數值類型之間可以隱式轉換的時候,數量才可以隱式轉換。N.B. 從double到int的轉換是顯式轉換,因為沒有辦法模仿內置轉換的準確行為。(???) 顯式構造可以支持以下兩種轉換:

  • explicit casting of a quantity to a different value_type :
    顯式將一個quantity轉換到不同的數值類型(value type)

quantity<si::length,int> L3 = static_cast<quantity<si::length,int> >(L1);

  • and explicit casting of a quantity to a different unit :
    顯式將一個quantity轉換到不同的單位:

quantity<cgs::length>    L4 = static_cast<quantity<cgs::length> >(L1);

giving the following output :

L1 = 2 m
L2 = 2 m
L3 = 2 m
L4 = 200 cm
L5 = 5 m
L6 = 4 m
L7 = 200 cm

A few more explicit unit system conversions :
幾個單位系統之間的顯式轉換:

quantity<si::volume>    vs(1.0*pow<3>(si::meter));      
quantity<cgs::volume>   vc(vs);
quantity<si::volume>    vs2(vc);
                    
quantity<si::energy>    es(1.0*si::joule);      
quantity<cgs::energy>   ec(es);
quantity<si::energy>    es2(ec);
                    
quantity<si::velocity>  v1 = 2.0*si::meters/si::second,     
                        v2(2.0*cgs::centimeters/cgs::second);

which produces the following output:

volume (m^3)  = 1 m^3
volume (cm^3) = 1e+06 cm^3
volume (m^3)  = 1 m^3

energy (joules) = 1 J
energy (ergs)   = 1e+07 erg
energy (joules) = 1 J

velocity (2 m/s)  = 2 m s^-1
velocity (2 cm/s) = 0.02 m s^-1

(quaternion.cpp)

This example demonstrates the use of boost::math::quaternion as a value type for quantity and the converse. For the first case, we first define specializations of power_typeof_helper and root_typeof_helper for powers and roots, respectively:
這個例子展示了使用boost::math::quaternion(四元數)作為quantity的數值類型(value type) and the converse(???)。 對於第一種情況,我們首先為乘方和開方定義power_typeof_helperroot_typeof_helper的特化

/// specialize power typeof helper
template<class Y,long N,long D> 
struct power_typeof_helper<boost::math::quaternion<Y>,static_rational<N,D> >
{ 
    // boost::math::quaternion only supports integer powers
    BOOST_STATIC_ASSERT(D==1);
    
    typedef boost::math::quaternion<
        typename power_typeof_helper<Y,static_rational<N,D> >::type
    > type; 
    
    static type value(const boost::math::quaternion<Y>& x)  
    {   
        return boost::math::pow(x,static_cast<int>(N));
    }
};

/// specialize root typeof helper
template<class Y,long N,long D> 
struct root_typeof_helper<boost::math::quaternion<Y>,static_rational<N,D> >
{ 
    // boost::math::quaternion only supports integer powers
    BOOST_STATIC_ASSERT(N==1);
    
    typedef boost::math::quaternion<
        typename root_typeof_helper<Y,static_rational<N,D> >::type
    > type; 
    
    static type value(const boost::math::quaternion<Y>& x)  
    { 
        return boost::math::pow(x,static_cast<int>(D));
    }
};

We can now declare a quantity of a quaternion :

typedef quantity<length,quaternion<double> >     length_dimension;
    
length_dimension    L(quaternion<double>(4.0,3.0,2.0,1.0)*meters);

so that all operations that are defined in the quaternion class behave correctly. If rational powers were defined for this class, it would be possible to compute rational powers and roots with no additional changes.
現在,我們定義於類quaternion上的操作符都可以正確執行了。 如果這個類定義了有理數乘方,那麼就可以直接計算乘方和開方了。

+L      = (4,3,2,1) m
-L      = (-4,-3,-2,-1) m
L+L     = (8,6,4,2) m
L-L     = (0,0,0,0) m
L*L     = (2,24,16,8) m^2
L/L     = (1,0,0,0) dimensionless 
L^3     = (-104,102,68,34) m^3

Now, if for some reason we preferred the quantity to be the value type of the quaternion class we would have :
如果我們將quantity作為quaternion的數值類型:

typedef quaternion<quantity<length> >     length_dimension;
    
length_dimension    L(4.0*meters,3.0*meters,2.0*meters,1.0*meters);

Here, the unary plus and minus and addition and subtraction operators function correctly. Unfortunately, the multiplication and division operations fail because quaternion implements them in terms of the *= and /= operators, respectively, which are incapable of representing the heterogeneous unit algebra needed for quantities (an identical problem occurs with std::complex<T>, for the same reason). In order to compute rational powers and roots, we need to specialize power_typeof_helper and root_typeof_helper as follows:
現在,取正、取負、加和減的操作都是正確的。 但不幸的是,乘和除失敗了,因為quaternion是通過*=/=實現的乘除。 這不能滿足數量的異構單位代數需要(同樣的問題也出現在std::complex<T>上)(???) 為了計算乘方和開方,我們需要特化power_typeof_helperroot_typeof_helper

/// specialize power typeof helper for quaternion<quantity<Unit,Y> >
template<class Unit,long N,long D,class Y> 
struct power_typeof_helper<
    boost::math::quaternion<quantity<Unit,Y> >,
    static_rational<N,D> >                
{ 
    typedef typename power_typeof_helper<
        Y,
        static_rational<N,D>
    >::type     value_type;

    typedef typename power_typeof_helper<
        Unit,
        static_rational<N,D>
    >::type  unit_type;

    typedef quantity<unit_type,value_type>         quantity_type;
    typedef boost::math::quaternion<quantity_type> type; 
    
    static type value(const boost::math::quaternion<quantity<Unit,Y> >& x)  
    { 
        const boost::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()));
        
        return type(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<class Unit,long N,long D,class Y> 
struct root_typeof_helper<
    boost::math::quaternion<quantity<Unit,Y> >,
    static_rational<N,D> >                
{ 
    typedef typename root_typeof_helper<
        Y,
        static_rational<N,D>
    >::type      value_type;

    typedef typename root_typeof_helper<
        Unit,
        static_rational<N,D>
    >::type   unit_type;

    typedef quantity<unit_type,value_type>         quantity_type;
    typedef boost::math::quaternion<quantity_type> type; 
    
    static type value(const boost::math::quaternion<quantity<Unit,Y> >& x)  
    { 
        const boost::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()));
        
        return type(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()));
    }
};

giving:

+L      = (4 m,3 m,2 m,1 m)
-L      = (-4 m,-3 m,-2 m,-1 m)
L+L     = (8 m,6 m,4 m,2 m)
L-L     = (0 m,0 m,0 m,0 m)
L^3     = (-104 m^3,102 m^3,68 m^3,34 m^3)

(complex.cpp)

This example demonstrates how to implement a replacement complex class that functions correctly both as a quantity value type and as a quantity container class, including heterogeneous multiplication and division operations and rational powers and roots. Naturally, heterogeneous operations are only supported on compilers that implement typeof. The primary differences are that binary operations are not implemented using the op= operators and use the utility classes add_typeof_helper, subtract_typeof_helper, multiply_typeof_helper, and divide_typeof_helper. In addition, power_typeof_helper and root_typeof_helper are defined for both cases :
這個例子展示了如何使用替代的complex類作為quantity的數值類型或quantity的存儲類,包括異構的乘、除、乘方和開方。 通常,異構的乘和除只有當編譯器實現typeof的時候才被支持。 這些二元運算的主要差別在於不是使用op=操作符,而是使用工具類add_typeof_helpersubtract_typeof_helpermultiply_typeof_helperdivide_typeof_helper。 另外,power_typeof_helperroot_typeof_helper在兩種情況下都會定義:

namespace boost {

namespace units {

/// replacement complex class 
template<class T>
class complex
{
    public:
        typedef complex<T>  this_type;
        
        complex(const T& r = 0,const T& i = 0) : r_(r),i_(i) { }
        complex(const this_type& source) : r_(source.r_),i_(source.i_) { }
        
        this_type& operator=(const this_type& source)
        {
            if (this == &source) return *this;
            
            r_ = source.r_;
            i_ = source.i_;
            
            return *this;
        }
        
        T& real()                   { return r_; }
        T& imag()                   { return i_; }
        
        const T& real() const       { return r_; }
        const T& imag() const       { return i_; }

        this_type& operator+=(const T& val)
        {
            r_ += val;
            return *this;
        }
        
        this_type& operator-=(const T& val)
        {
            r_ -= val;
            return *this;
        }
        
        this_type& operator*=(const T& val)
        {
            r_ *= val;
            i_ *= val;
            return *this;
        }
        
        this_type& operator/=(const T& val)
        {
            r_ /= val;
            i_ /= val;
            return *this;
        }
        
        this_type& operator+=(const this_type& source)
        {
            r_ += source.r_;
            i_ += source.i_;
            return *this;
        }
        
        this_type& operator-=(const this_type& source)
        {
            r_ -= source.r_;
            i_ -= source.i_;
            return *this;
        }
        
        this_type& operator*=(const this_type& source)
        {
            *this = *this * source;
            return *this;
        }
        
        this_type& operator/=(const this_type& source)
        {
            *this = *this / source;
            return *this;
        }
        
    private:
        T   r_,i_;
};

}

}

#if BOOST_UNITS_HAS_BOOST_TYPEOF

#include BOOST_TYPEOF_INCREMENT_REGISTRATION_GROUP()

BOOST_TYPEOF_REGISTER_TEMPLATE(boost::units::complex, 1)

#endif

namespace boost {

namespace units {

template<class X>
complex<typename unary_plus_typeof_helper<X>::type>
operator+(const complex<X>& x)
{
    typedef typename unary_plus_typeof_helper<X>::type  type;
    
    return complex<type>(x.real(),x.imag());
}

template<class X>
complex<typename unary_minus_typeof_helper<X>::type>
operator-(const complex<X>& x)
{
    typedef typename unary_minus_typeof_helper<X>::type type;
    
    return complex<type>(-x.real(),-x.imag());
}

template<class X,class Y>
complex<typename add_typeof_helper<X,Y>::type>
operator+(const complex<X>& x,const complex<Y>& y)
{
    typedef typename boost::units::add_typeof_helper<X,Y>::type type;
    
    return complex<type>(x.real()+y.real(),x.imag()+y.imag());
}

template<class X,class Y>
complex<typename boost::units::subtract_typeof_helper<X,Y>::type>
operator-(const complex<X>& x,const complex<Y>& y)
{
    typedef typename boost::units::subtract_typeof_helper<X,Y>::type    type;
    
    return complex<type>(x.real()-y.real(),x.imag()-y.imag());
}

template<class X,class Y>
complex<typename boost::units::multiply_typeof_helper<X,Y>::type>
operator*(const complex<X>& x,const complex<Y>& y)
{
    typedef typename boost::units::multiply_typeof_helper<X,Y>::type    type;
    
    return complex<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<class X,class Y>
complex<typename boost::units::divide_typeof_helper<X,Y>::type>
operator/(const complex<X>& x,const complex<Y>& y)
{
    // naive implementation of complex division
    typedef typename boost::units::divide_typeof_helper<X,Y>::type type;

    return complex<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<class Y>
complex<Y> 
pow(const complex<Y>& x,const Y& y)
{
    std::complex<Y> tmp(x.real(),x.imag());
    
    tmp = std::pow(tmp,y);
    
    return complex<Y>(tmp.real(),tmp.imag());
}

template<class Y>
std::ostream& operator<<(std::ostream& os,const complex<Y>& val)
{
    os << val.real() << " + " << val.imag() << " i";

    return os;
}

/// specialize power typeof helper for complex<Y>
template<class Y,long N,long D> 
struct power_typeof_helper<complex<Y>,static_rational<N,D> >                
{ 
    typedef complex<
        typename power_typeof_helper<Y,static_rational<N,D> >::type
    > type; 
    
    static type value(const complex<Y>& x)  
    { 
        const static_rational<N,D>  rat;

        const Y    m = Y(rat.numerator())/Y(rat.denominator());
        
        return boost::units::pow(x,m);
    }
};

/// specialize root typeof helper for complex<Y>
template<class Y,long N,long D> 
struct root_typeof_helper<complex<Y>,static_rational<N,D> >                
{ 
    typedef complex<
        typename root_typeof_helper<Y,static_rational<N,D> >::type
    > type; 
    
    static type value(const complex<Y>& x)  
    { 
        const static_rational<N,D>  rat;

        const Y    m = Y(rat.denominator())/Y(rat.numerator());
        
        return boost::units::pow(x,m);
    }
};

/// specialize power typeof helper for complex<quantity<Unit,Y> >
template<class Y,class Unit,long N,long D> 
struct power_typeof_helper<complex<quantity<Unit,Y> >,static_rational<N,D> >
{ 
    typedef typename
        power_typeof_helper<Y,static_rational<N,D> >::type       value_type;
    typedef typename
        power_typeof_helper<Unit,static_rational<N,D> >::type    unit_type;
    typedef quantity<unit_type,value_type>                      quantity_type;
    typedef complex<quantity_type>                              type; 
    
    static type value(const complex<quantity<Unit,Y> >& x)  
    { 
        const complex<value_type>   tmp =
            pow<static_rational<N,D> >(complex<Y>(x.real().value(),
                                                  x.imag().value()));
        
        return type(quantity_type::from_value(tmp.real()),
                    quantity_type::from_value(tmp.imag()));
    }
};

/// specialize root typeof helper for complex<quantity<Unit,Y> >
template<class Y,class Unit,long N,long D> 
struct root_typeof_helper<complex<quantity<Unit,Y> >,static_rational<N,D> >
{ 
    typedef typename
        root_typeof_helper<Y,static_rational<N,D> >::type       value_type;
    typedef typename
        root_typeof_helper<Unit,static_rational<N,D> >::type    unit_type;
    typedef quantity<unit_type,value_type>                      quantity_type;
    typedef complex<quantity_type>                              type; 
    
    static type value(const complex<quantity<Unit,Y> >& x)  
    { 
        const complex<value_type>   tmp =
            root<static_rational<N,D> >(complex<Y>(x.real().value(),
                                                   x.imag().value()));
        
        return type(quantity_type::from_value(tmp.real()),
                   quantity_type::from_value(tmp.imag()));
    }
};

} // namespace units

} // namespace boost

With this replacement complex class, we can declare a complex variable :
使用這個替代的complex,我們定義一個複數變量:

typedef quantity<length,complex<double> >     length_dimension;
    
length_dimension    L(complex<double>(2.0,1.0)*meters);

to get the correct behavior for all cases supported by quantity with a complex value type :
能看到使用complex作為數值類型的quantity支持的所有操作:

+L      = 2 + 1 i m
-L      = -2 + -1 i m
L+L     = 4 + 2 i m
L-L     = 0 + 0 i m
L*L     = 3 + 4 i m^2
L/L     = 1 + 0 i dimensionless
L^3     = 2 + 11 i m^3
L^(3/2) = 2.56713 + 2.14247 i m^(3/2)
3vL     = 1.29207 + 0.201294 i m^(1/3)
(3/2)vL = 1.62894 + 0.520175 i m^(2/3)

and, similarly, complex with a quantity value type
類似的,用quantity作為數值類型的complex

typedef complex<quantity<length> >     length_dimension;
    
length_dimension    L(2.0*meters,1.0*meters);

gives

+L      = 2 m + 1 m i
-L      = -2 m + -1 m i
L+L     = 4 m + 2 m i
L-L     = 0 m + 0 m i
L*L     = 3 m^2 + 4 m^2 i
L/L     = 1 dimensionless + 0 dimensionless i
L^3     = 2 m^3 + 11 m^3 i
L^(3/2) = 2.56713 m^(3/2) + 2.14247 m^(3/2) i
3vL     = 1.29207 m^(1/3) + 0.201294 m^(1/3) i
(3/2)vL = 1.62894 m^(2/3) + 0.520175 m^(2/3) i

(performance.cpp)

This example provides an ad hoc performance test to verify that zero runtime overhead is incurred when using quantity in place of double. Note that performance optimization and testing is not trivial, so some care must be taken in profiling. It is also critical to have a compiler capable of optimizing the many template instantiations and inline calls effectively to achieve maximal performance. Zero overhead for this test has been verified using gcc 4.0.1, and icc 9.0, 10.0, and 10.1 on Mac OS 10.4 and 10.5, and using msvc 8.0 on Windows XP.
這個例子展示了一個專門的性能測試來說明用quantity代替double不會引入運行時開銷。 運行優化和測試不是微不足道的,所以在剖析時某些地方必須注意。 編譯器優化模板實例化的能力和inline調用的能力是很重要的。 零開銷已經在下面的編譯器和平台上被證明了:gcc 4.0.1, and icc 9.0, 10.0, and 10.1 on Mac OS 10.4 and 10.5, and using msvc 8.0 on Windows XP。

(radar_beam_height.cpp)

This example demonstrates the implementation of two non-SI units of length, the nautical mile :
這個例子展示了兩個非SI長度單位的實現,海裡:

namespace nautical {

struct length_base_unit : 
    boost::units::base_unit<length_base_unit, length_dimension, 1>
{
    static std::string name()       { return "nautical mile"; }
    static std::string symbol()     { return "nmi"; }
};

typedef boost::units::make_system<length_base_unit>::type system;

/// unit typedefs
typedef unit<length_dimension,system>    length;

static const length mile,miles;

} // namespace nautical

// helper for conversions between nautical length and si length
BOOST_UNITS_DEFINE_CONVERSION_FACTOR(nautical::length_base_unit,
                                     boost::units::si::meter_base_unit,
                                     double, 1.852e3);

and the imperial foot :
和英制的尺:

namespace imperial {

struct length_base_unit : 
    boost::units::base_unit<length_base_unit, length_dimension, 2>
{
    static std::string name()       { return "foot"; }
    static std::string symbol()     { return "ft"; }
};

typedef boost::units::make_system<length_base_unit>::type system;

/// unit typedefs
typedef unit<length_dimension,system>    length;

static const length foot,feet;

} // imperial

// helper for conversions between imperial length and si length
BOOST_UNITS_DEFINE_CONVERSION_FACTOR(imperial::length_base_unit,
                                     boost::units::si::meter_base_unit,
                                     double, 1.0/3.28083989501312);

These units include conversions between themselves and the meter. Three functions for computing radar beam height from radar range and the local earth radius are defined. The first takes arguments in one system and returns a value in the same system :
這些單位和米之間都存在著轉換關係。 三個通過雷達範圍和當地地球半徑計算雷達截面高度的函數被定義了。 第一個函數以一個單位系統為參數,返回同樣單位系統的值:

template<class System,typename T>
quantity<unit<boost::units::length_dimension,System>,T>
radar_beam_height(const quantity<unit<length_dimension,System>,T>& radar_range,
                  const quantity<unit<length_dimension,System>,T>& earth_radius,
                  T k = 4.0/3.0)
{
    return quantity<unit<length_dimension,System>,T>
        (pow<2>(radar_range)/(2.0*k*earth_radius));
}

The second is similar, but is templated on return type, so that the arguments are converted to the return unit system internally :
第二個函數類似,只是將返回值模板化了,這樣參數就在內部被轉換為返回值的單位系統:

template<class return_type,class System1,class System2,typename T>
return_type
radar_beam_height(const quantity<unit<length_dimension,System1>,T>& radar_range,
                  const quantity<unit<length_dimension,System2>,T>& earth_radius,
                  T k = 4.0/3.0)
{
    // need to decide which system to use for calculation
    const return_type   rr(radar_range),
                        er(earth_radius);

    return return_type(pow<2>(rr)/(2.0*k*er));
}

Finally, the third function is an empirical approximation that is only valid for radar ranges specified in nautical miles, returning beam height in feet. This function uses the heterogeneous unit of nautical miles per square root of feet to ensure dimensional correctness :
最後,第三個函數是一個經驗公式(empirical approximation不會譯),只有當雷達範圍的單位是海裡,返回的截面高度是英尺時才正確。 這個函數使用了異構的單位,nautical miles per square root of feet:

quantity<imperial::length>
radar_beam_height(const quantity<nautical::length>& range)
{
    return quantity<imperial::length>
        (pow<2>(range/(1.23*nautical::miles/root<2>(imperial::feet))));
}

With these, we can compute radar beam height in various unit systems :
這樣,我們可以用不同的單位系統來計算雷達截面高度:

const quantity<nautical::length> radar_range(300.0*miles);
const quantity<si::length>       earth_radius(6371.0087714*kilo*meters);

const quantity<si::length>       beam_height_1(radar_beam_height(quantity<si::length>(radar_range),earth_radius));
const quantity<nautical::length> beam_height_2(radar_beam_height(radar_range,quantity<nautical::length>(earth_radius)));
const quantity<si::length>       beam_height_3(radar_beam_height< quantity<si::length> >(radar_range,earth_radius));
const quantity<nautical::length> beam_height_4(radar_beam_height< quantity<nautical::length> >(radar_range,earth_radius));

giving

radar range        : 300 nmi
earth radius       : 6.37101e+06 m
beam height 1      : 18169.7 m
beam height 2      : 9.81085 nmi
beam height 3      : 18169.7 m
beam height 4      : 9.81085 nmi
beam height approx : 59488.4 ft
beam height approx : 18132.1 m

(heterogeneous_unit.cpp)

Mixed units and mixed unit conversions.
混合單位及其轉換。

This code:

quantity<si::length>        L(1.5*si::meter);
quantity<cgs::mass>         M(1.0*cgs::gram);

std::cout << L << std::endl
          << M << std::endl
          << L*M << std::endl
          << L/M << std::endl
          << std::endl;
          
std::cout << 1.0*si::meter*si::kilogram/pow<2>(si::second) << std::endl
          << 1.0*si::meter*si::kilogram/pow<2>(si::second)/si::meter
          << std::endl << std::endl;

std::cout << 1.0*cgs::centimeter*si::kilogram/pow<2>(si::second) << std::endl
          << 1.0*cgs::centimeter*si::kilogram/pow<2>(si::second)/si::meter
          << std::endl << std::endl;

gives

1.5 m
1 g
1.5 m g
1.5 m g^-1

1 N
1 kg s^-2

1 cm kg s^-2
1 cm m^-1 kg s^-2

Arbitrary conversions also work:
任意的轉換也可以工作:

quantity<si::area>      A(1.5*si::meter*cgs::centimeter);

std::cout << 1.5*si::meter*cgs::centimeter << std::endl
          << A << std::endl
          << std::endl;

yielding

1.5 cm m
0.015 m^2

(temperature.cpp)

This example demonstrates using of absolute temperatures and relative temperature differences in Fahrenheit and converting between these and the Kelvin temperature scale. This issue touches on some surprisingly deep mathematical concepts (see Wikipedia for a basic review), but for our purposes here, we will simply observe that it is important to be able to differentiate between an absolute temperature measurement and a measurement of temperature difference. This is accomplished by using the absolute wrapper class.
這個例子展示了使用絕對溫度和華氏相對溫度,以及與開爾文溫度之間的轉換。(???) 這部分會涉及到一些很深的數學概念(見Wikipedia), 但對於我們來說,只是知道區分一個絕對的溫度度量和溫度差異度量是非常重要的。 這是通過使用外覆類absolute來實現的。

First we define a system using the predefined fahrenheit base unit:
首先,我們使用預定義的華氏基礎單位來定義一個系統:

typedef temperature::fahrenheit_base_unit::unit_type    temperature;
typedef get_system<temperature>::type                   system;

BOOST_UNITS_STATIC_CONSTANT(degree,temperature);
BOOST_UNITS_STATIC_CONSTANT(degrees,temperature);

Now we can create some quantities:
然後創建一個數量:

quantity<absolute<fahrenheit::temperature> >    T1p(
    32.0*absolute<fahrenheit::temperature>());
quantity<fahrenheit::temperature>               T1v(
    32.0*fahrenheit::degrees);

quantity<absolute<si::temperature> >            T2p(T1p);
quantity<si::temperature>                       T2v(T1v);

Note the use of absolute to wrap a unit. The resulting output is:
注意absolute的使用。輸出如下:

{ 32 } F
{ 273.15 } K
{ 273.15 } K
[ 32 ] F
[ 17.7778 ] K
[ 17.7778 ] K

(runtime_conversion_factor.cpp)

The Boost.Units library does not require that the conversion factors be compile time constants, as is demonstrated in this example:
Boost.Units庫並不要求轉換因子是編譯時常量,就像下面例子展示的:

using boost::units::base_dimension;
using boost::units::base_unit;

static const long currency_base = 1;

struct currency_base_dimension : base_dimension<currency_base_dimension, 1> {};

typedef currency_base_dimension::dimension_type currency_type;

template<long N>
struct currency_base_unit :
    base_unit<currency_base_unit<N>, currency_type, currency_base + N> {};

typedef currency_base_unit<0> us_dollar_base_unit;
typedef currency_base_unit<1> euro_base_unit;

typedef us_dollar_base_unit::unit_type us_dollar;
typedef euro_base_unit::unit_type euro;

// an array of all possible conversions
double conversion_factors[2][2] = {
    {1.0, 1.0},
    {1.0, 1.0}
};

double get_conversion_factor(long from, long to) {
    return(conversion_factors[from][to]);
}

void set_conversion_factor(long from, long to, double value) {
    conversion_factors[from][to] = value;
    conversion_factors[to][from] = 1.0 / value;
}

BOOST_UNITS_DEFINE_CONVERSION_FACTOR_TEMPLATE((long N1)(long N2),
    currency_base_unit<N1>,
    currency_base_unit<N2>,
    double, get_conversion_factor(N1, N2));

(non_base_dimension.cpp)

It is also possible to define base units that have derived rather than base dimensions:
同樣可以不從基礎量綱派生定義基礎單位(???):

struct imperial_gallon_tag :
    base_unit<imperial_gallon_tag, volume_dimension, 1> { };

typedef make_system<imperial_gallon_tag>::type imperial;

typedef unit<volume_dimension,imperial> imperial_gallon;

struct us_gallon_tag : base_unit<us_gallon_tag, volume_dimension, 2> { };

typedef make_system<us_gallon_tag>::type us;

typedef unit<volume_dimension,us> us_gallon;

(composite_output.cpp)

If a unit has a special name and/or symbol, the free functions name_string and symbol_string can be overloaded directly.
如果一個單位有特殊的名字(name)和/或符號(symbol),自由函數name_stringsymbol_string可以被直接重載。

std::string name_string(const cgs::force&)
{
    return "dyne";
}

std::string symbol_string(const cgs::force&)
{
    return "dyn";
}

In this case, any unit that reduces to the overloaded unit will be output with the replacement symbol.
這樣,任何可以化簡到重載單位的單位輸出都可以用這個替代符號。

Special names and symbols for the SI and CGS unit systems are found in boost/units/systems/si/io.hpp and boost/units/systems/cgs/io.hpp, respectively. If these headers are not included, the output will simply follow default rules using the appropriate fundamental dimensions. Note that neither of these functions is defined for quantities because doing so would require making assumptions on how the corresponding value type should be formatted.
SI和CGS單位系統專門的名字和符號可以分別在boost/units/systems/si/io.hppboost/units/systems/cgs/io.hpp文件中找到。 如果這些頭文件沒有被包含,輸出會簡單地使用基本量綱(fundamental dimension)的規則輸出。 這些函數都沒有為數量(quantity)定義,因為如果那麼做的話就會要求假定相關的數值類型(value type)是如何輸出的。

Three ostream formatters, symbol_format, name_format, and typename_format are provided for convenience. These select the textual representation of units provided by symbol_string or name_string in the first two cases, while the latter returns a demangled typename for debugging purposes. Formatting of scaled unit is also done correctly.
三個ostream格式程序(symbol_formatname_formattypename_format)提供了方便。 前兩個使用symbol_stringname_string提供的字符串,後一個提供了調試用的重整過的類型定義。 成比例單位同樣能夠被正確地格式化。

This code demonstrates the use of the conversion_factor free function to determine the scale factor between two units.
這個例子展示了使用自由函數conversion_factor來確定兩個單位之間的比例係數。

(conversion_factor.cpp)

double dyne_to_newton =
    conversion_factor(cgs::dyne,si::newton);
std::cout << dyne_to_newton << std::endl;

double force_over_mass_conversion =
    conversion_factor(si::newton/si::kilogram,cgs::dyne/cgs::gram);
std::cout << force_over_mass_conversion << std::endl;

double momentum_conversion =
    conversion_factor(cgs::momentum(),si::momentum());
std::cout << momentum_conversion << std::endl;

double momentum_over_mass_conversion =
    conversion_factor(si::momentum()/si::mass(),cgs::momentum()/cgs::gram);
std::cout << momentum_over_mass_conversion << std::endl;

double acceleration_conversion =
    conversion_factor(cgs::gal,si::meter_per_second_squared);
std::cout << acceleration_conversion << std::endl;

Produces

1e-005
100
1e-005
100
0.01

(runtime_unit.cpp)

This example shows how to implement an interface that allow different units at runtime while still maintaining type safety for internal calculations.
這個例子展示了如何實現一個接口,能夠在運行時接受不同的單位並維持類型安全和內部和計算。

namespace {

using namespace boost::units;
using imperial::foot_base_unit;

std::map<std::string, quantity<si::length> > known_units;

}

quantity<si::length> calculate(const quantity<si::length>& t) 
{
    return(boost::units::hypot(t, 2.0 * si::meters));
}

int main() 
{
    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::string output_type("meter");
    std::string input;
    
    while((std::cout << "> ") && (std::cin >> input)) 
    {
        if(!input.empty() && input[0] == '#') 
        {
            std::getline(std::cin, input);
        }
        else if(input == "exit") 
        {
            break;
        }
        else if(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;
        } 
        else if(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 
            {
                double value = 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;
            }
        }
    }
}

(lambda.cpp)

The header boost/units/lambda.hpp provides overloads and specializations needed to make Boost.Units usable with the Boost.Lambda library.
頭文件boost/units/lambda.hpp中提供了Boost.Units被Boost.Lambda使用所需的重載和特化。

int main(int argc, char **argv) {

   using namespace std;
   namespace bl = boost::lambda;
   namespace bu = boost::units;
   namespace si = boost::units::si;


   ////////////////////////////////////////////////////////////////////////
   // Mechanical example: linear accelerated movement
   ////////////////////////////////////////////////////////////////////////

   // Initial condition variables for acceleration, speed, and displacement
   bu::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 time
   boost::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 conditions
   a = 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 current
   const bu::quantity<si::current> iamp = 1.5 * si::ampere;
   const bu::quantity<si::frequency> f = 1.0e3 * si::hertz;
   const bu::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 (*)(const bu::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 constant
   const bu::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> (*)(const bu::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 constants
   const bu::quantity<bu::absolute<si::temperature> >
       Tref = 273.15 * bu::absolute<si::temperature>();
   const bu::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;


   return 0;
}


PrevUpHomeNext