📄 units.qbk
字号:
[library Boost.Units [quickbook 1.3] [version 1.0.0] [authors [Schabel, Matthias C.]] [authors [Watanabe, Steven]] [copyright 2003-2008 Matthias Christian Schabel, 2007-2008 Steven Watanabe] [license 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]) ] [purpose zero-overhead compile-time dimensional analysis and unit computations]][def __boost_mpl [@http://www.boost.org/libs/mpl/doc/index.html Boost Metaprogramming Library]][def __mpl_forward_sequence [@http://www.boost.org/libs/mpl/doc/refmanual/forward-sequence.html MPL Forward Sequence]][def __ordinal [classref boost::units::ordinal ordinal]][def __dim [classref boost::units::dim dim]][def __static_rational [classref boost::units::static_rational static_rational]][def __make_dimension_list [classref boost::units::make_dimension_list make_dimension_list]][def __unit [classref boost::units::unit unit]][def __base_unit_info [classref boost::units::base_unit_info base_unit_info]][def __quantity [classref boost::units::quantity quantity]][def __conversion_helper [classref boost::units::conversion_helper conversion_helper]][def __absolute [classref boost::units::absolute absolute]][def __base_unit [classref boost::units::base_unit base_unit]][def __base_dimension [classref boost::units::base_dimension base_dimension]][def __scaled_base_unit [classref boost::units::scaled_base_unit base_unit]][def __make_scaled_unit [classref boost::units::make_scaled_unit make_scaled_unit]][def __unary_plus_typeof_helper [classref boost::units::unary_plus_typeof_helper unary_plus_typeof_helper]][def __unary_minus_typeof_helper [classref boost::units::unary_minus_typeof_helper unary_minus_typeof_helper]][def __add_typeof_helper [classref boost::units::add_typeof_helper add_typeof_helper]][def __subtract_typeof_helper [classref boost::units::subtract_typeof_helper subtract_typeof_helper]][def __multiply_typeof_helper [classref boost::units::multiply_typeof_helper multiply_typeof_helper]][def __divide_typeof_helper [classref boost::units::divide_typeof_helper divide_typeof_helper]][def __power_typeof_helper [classref boost::units::power_typeof_helper power_typeof_helper]][def __root_typeof_helper [classref boost::units::root_typeof_helper root_typeof_helper]][def __static_negate [classref boost::units::static_negate static_negate]][def __static_add [classref boost::units::static_add static_add]][def __static_subtract [classref boost::units::static_subtract static_subtract]][def __static_multiply [classref boost::units::static_multiply static_multiply]][def __static_divide [classref boost::units::static_divide static_divide]][def __static_power [classref boost::units::static_power static_power]][def __static_root [classref boost::units::static_root static_root]][def __get_dimension [classref boost::units::get_dimension get_dimension]][def __get_system [classref boost::units::get_system get_system]][def __pow [funcref boost::units::pow pow]][def __root [funcref boost::units::root root]][def __quantity_cast [funcref boost::units::quantity_cast quantity_cast]][def __from_value [memberref boost::units::quantity::from_value from_value]][def __value [memberref boost::units::quantity::value value]][def __reduce_unit [classref boost::units::reduce_unit reduce_unit]][def __unscale [classref boost::units::unscale unscale]][def __BOOST_UNITS_STATIC_CONSTANT [macroref BOOST_UNITS_STATIC_CONSTANT]][def __BOOST_UNITS_DEFINE_CONVERSION_FACTOR [macroref BOOST_UNITS_DEFINE_CONVERSION_FACTOR]][def __BOOST_UNITS_DEFINE_CONVERSION_FACTOR_TEMPLATE [macroref BOOST_UNITS_DEFINE_CONVERSION_FACTOR_TEMPLATE]][def __BOOST_UNITS_DEFAULT_CONVERSION [macroref BOOST_UNITS_DEFAULT_CONVERSION]][section:Introduction Introduction]The Boost.Units library is a C++ implementation of dimensional analysis in a general and extensible manner, treating it as a generic compile-time metaprogramming problem. With appropriatecompiler optimization, no runtime execution cost is introduced, facilitating the use of this library toprovide dimension checking in performance-critical code. Support for unitsand quantities (defined as a unit and associated value) for arbitrary unit system models and arbitrary value types is provided, as is a fine-grained general facility for unit conversions. Complete SI and CGS unit systems are provided, along with systems for angles measured in degrees, radians, gradians, and revolutions and systems for temperatures measured in Kelvin, degrees Celsius and degrees Fahrenheit. The library architecture has been designed with flexibility and extensibility in mind; demonstrations of the easeof adding new units and unit conversions are provided in the examples.In order to enable complex compile-time dimensional analysis calculations with no runtime overhead,Boost.Units relies heavily on the [___boost_mpl] (MPL) and on template metaprogramming techniques, and is, as a consequence, fairly demanding of compiler compliance to ISO standards. At present, it has been successfullycompiled and tested on the following compilers/platforms :# g++ 4.0.1 on Mac OSX 10.4# Intel CC 9.1, 10.0, and 10.1 on Mac OSX 10.4# g++ 3.4.4, 4.2.3, and 4.3.0 on Windows XP# Microsoft Visual C++ 7.1, 8.0, and 9.0 on Windows XP# Metrowerks CodeWarrior 9.2 on Windows XP. The following compilers/platforms are known *not* to work :# g++ 3.3.x# Microsoft Visual C++ 6.0 on Windows XP# Microsoft Visual C++ 7.0 on Windows XP# Metrowerks CodeWarrior 8.0 on Windows XP.[endsect][section:Quick_Start Quick Start]Before discussing the basics of the library, we first define a few terms that will be used frequentlyin the following :* *Base dimension* : A base dimension is loosely defined as a measurable entity of interest; in conventional dimensional analysis, base dimensions include length (\[L\]), mass (\[M\]), time (\[T\]), etc... but there is no specific restriction on what base dimensions can be used. Base dimensions are essentially a tag type and provide no dimensional analysis functionality themselves.* *Dimension* : A collection of zero or more base dimensions, each potentially raised to a different rational power. For example, area = \[L\]^2, velocity = \[L\]^1/\[T\]^1, and energy = \[M\]^1 \[L\]^2/\[T\]^2 are all dimensions.* *Base unit* : A base unit represents a specific measure of a dimension. For example, while length is an abstract measure of distance, the meter is a concrete base unit of distance. Conversions are defined using base units. Much like base dimensions, base units are a tag type used solely to define units and do not support dimensional analysis algebra.* *Unit* : A set of base units raised to rational exponents, e.g. kg^1 m^1/s^2.* *System* : A unit system is a collection of base units representing all the measurable entities of interest for a specific problem. For example, the SI unit system defines seven base units : length (\[L\]) in meters, mass (\[M\]) in kilograms, time (\[T\]) in seconds, current (\[I\]) in amperes, temperature (\[theta\]) in kelvin, amount (\[N\]) in moles, and luminous intensity (\[J\]) in candelas. All measurable entities within the SI system can be represented as products of various integer or rational powers of these seven base units.* *Quantity* : A quantity represents a concrete amount of a unit. Thus, while the meter is the base unit of length in the SI system, 5.5 meters is a quantity of length in that system.To begin, we present two short tutorials. [@../../libs/units/tutorial/tutorial_1.cpp Tutorial1] demonstrates the use of [@http://en.wikipedia.org/wiki/SI_units SI] units. After including the appropriate system headers and the headers for the various SI units we will need (all SI units can be included with [headerref boost/units/systems/si.hpp]) and for quantity I/O ([headerref boost/units/io.hpp]), we define a function that computes the work, in joules, done by exerting a force in newtons over a specified distance in meters and outputs the result to `std::cout`. The [___quantity] class accepts a second template parameter as its value type; this parameter defaults to`double` if not otherwise specified. To demonstrate the ease of using user-defined types in dimensionalcalculations, we also present code for computing the complex impedance using `std::complex<double>`as the value type :[import ../example/tutorial.cpp][tutorial_code]The intent and function of the above code should be obvious; the output produced is :[tutorial_output]While this library attempts to make simple dimensional computations easy to code, it is in no waytied to any particular unit system (SI or otherwise). Instead, it provides a highly flexible compile-timesystem for dimensional analysis, supporting arbitrary collections of base dimensions, rational powers of units, and explicit quantity conversions. It accomplishes all of this via template metaprogramming techniques. With modern optimizing compilers, this results in zero runtime overhead for quantity computations relative to the same code without unit checking.[endsect][section:Dimensional_Analysis Dimensional Analysis]The concept of [@http://en.wikipedia.org/wiki/Dimensional_analysis dimensional analysis] is normally presented early on in introductory physics and engineering classes as a means of determining the correctness of an equation or computation by propagating the physical measurement[@http://en.wikipedia.org/wiki/Units_of_measurement units]of various quantities through the equation along with their numerical values. There are a number of standard unit systems in common use, the most prominent of which is the [@http://en.wikipedia.org/wiki/SI_units Systeme International] (also known as SI or MKS (meter-kilogram-second), which was a metric predecessor to the SI system named for three of the base units on which the system is based). The SI is the only official international standard unit system and is widely utilized in science and engineering. Other common systems include the [@http://en.wikipedia.org/wiki/Cgs_units CGS](centimeter-gram-second) system and the [@http://en.wikipedia.org/wiki/English_units English]system still in use in some problem domains in the United States and elsewhere. In physics, there also exist a number of other systems that are in common use in specialized subdisciplines. These are collectively referred to as [@http://en.wikipedia.org/wiki/Natural_units natural units]. When quantities representing different measurables are combined, dimensional analysis provides the means of assessing the consistency of the resulting calculation. For example, the sum of two lengths is also a length, while the product of two lengths is an area, and the sum of a length and an area is undefined. The fact that thearguments to many functions (such as exp, log, etc...) must be dimensionless quantities can be easily demonstrated by examining their series expansions in the context of dimensional analysis. This library facilitates the enforcement of this type of restriction in code involving dimensioned quantities where appropriate.In the following discussion we view dimensional analysis as an abstraction in which an arbitrary set of [@http://en.wikipedia.org/wiki/Fundamental_units units] obey the rules of a specific algebra. We will refer to a pair of a base dimension and a rational exponent as a *fundamental dimension*, and a list composed of an arbitrary number of fundamental dimensions as a *composite dimension* or, simply,*dimension*. In particular, given a set of [$../../libs/units/images/form_0.png] fundamental dimensionsdenoted by [$../../libs/units/images/form_1.png] and a set of [$../../libs/units/images/form_0.png]rational exponents [$../../libs/units/images/form_2.png], any possible (composite) dimension can be writtenas [$../../libs/units/images/form_3.png]. Composite dimensions obey the algebraic rules for dimensional analysis. In particular, for any scalar value,[$../../libs/units/images/form_4.png], and composite dimensions [$../../libs/units/images/form_5.png]and [$../../libs/units/images/form_6.png], where [$../../libs/units/images/form_7.png], we have:[$../../libs/units/images/form_8.png]Users of a dimensional analysis library should be able to specify an arbitrary list of base dimensions to produce a composite dimension. This potentially includes repeated tags. For example, it should be possible to express energy as [$../../libs/units/images/form_9.png], [$../../libs/units/images/form_10.png], [$../../libs/units/images/form_11.png], or any other permutation of mass, length, and time having aggregate exponents of 1, 2, and -2, respectively.In order to be able to perform computations on arbitrary sets of dimensions, all composite dimensions must be reducible to an unambiguous final composite dimension, which we will refer to as a *reduced dimension*, for which# fundamental dimensions are consistently ordered# dimensions with zero exponent are elided. Note that reduced dimensions never have more than [$../../libs/units/images/form_0.png] base dimensions, one for each distinct fundamental dimension, but may have fewer.In our implementation, base dimensions are associated with tag types. As we will ultimately represent composite dimensions as typelists, we must provide some mechanism for sortingbase dimension tags in order to make it possible to convert an arbitrary composite dimensioninto a reduced dimension. For this purpose, we assign a unique integer to each base dimension.The [___base_dimension] class (found in [headerref boost/units/base_dimension.hpp]) uses thecuriously recurring template pattern (CRTP) technique to ensure that ordinals specified forbase dimensions are unique: template<class Derived, long N> struct base_dimension { ... };With this, we can define the base dimensions for length, mass, and time as:[import ../example/test_system.hpp][test_system_snippet_1]It is important to note that the choice of order is completely arbitrary as long as each tag has a unique enumerablevalue; non-unique ordinals are flagged as errors at compile-time. Negative ordinals are reserved for use by the library. To define composite dimensions corresponding to the base dimensions, wesimply create MPL-conformant typelists of fundamental dimensions by using the [___dim] class to encapsulate pairs of base dimensions and [___static_rational] exponents. The [___make_dimension_list] class acts as a wrapper to ensurethat the resulting type is in the form of a reduced dimension:[test_system_snippet_2]This can also be easily accomplished using a convenience typedef provided by [___base_dimension]:[test_system_snippet_3]so that the above code is identical to the full typelist definition. Composite dimensions are similarly defined via a typelist:[test_system_snippet_4]A convenience class for composite dimensions with integer powers is also provided:[test_system_snippet_5][endsect][section:Units Units]We define a *unit* as a linear combination of base units. Thus, the SI unit correspondingto the dimension of force is kg m s^-2, where kg, m, and s are base units. We use thenotion of a *unit system* such as SI to specify the mapping from a dimension to aparticular unit so that instead of specifying the base units explicitly, we can justask for the representation of a dimension in a particular system.Units are, like dimensions, purely compile-time variables with no associated value.Units obey the same algebra as dimensions do; the presence of the unit system serves to ensure that units having identicalreduced dimension in different systems (like feet and meters) cannot be inadvertently mixed in computations.There are two distinct types of systems that can be envisioned:* *Homogeneous systems* : Systems which hold a linearly independent set of base units which can be used to represent many different dimensions. For example, the SI system has seven base dimensions and seven base units corresponding to them. It can represent any unit which uses only those seven base dimensions. Thus it is a homogeneous_system.* *Heterogeneous systems* : Systems which store the exponents of every base unit involved are termed heterogeneous. Some units can only be represented in this way. For example, area in m ft is intrinsically heterogeneous, because the base units of meters and feet have identical dimensions. As a result, simply storing a dimension and a set of base units does not yield a unique solution. A practical example of the need for heterogeneous units, is an empirical equation used in aviation: H = (r/C)^2 where H is the radar beam height in feet and r is the radar range in nautical miles. In order to enforce dimensional correctness of this equation, the constant, C, must be expressed in nautical miles per foot^(1/2), mixing two distinct base units of length.Units are implemented by the [___unit] template class defined in [headerref boost/units/unit.hpp] : template<class Dim,class System> class unit;In addition to supporting the compile-time dimensional analysis operations, the +, -, *, and / runtime operators are providedfor [___unit] variables. Because the dimension associated with powers and roots must be computed at compile-time, it is not possible to provide overloads for `std::pow` that function correctly for [___unit]s. These operations are supported through free functions [___pow] and [___root] that are templated on integer and [___static_rational] values and can take as an argument any type for which the utility classes [___power_typeof_helper] and [___root_typeof_helper] have been defined.[section Base Units]Base units are defined much like base dimensions. template<class Derived, class Dimensions, long N> struct base_unit { ... };Again negative ordinals are reserved.As an example, in the following we will implement a subset of the SI unit system based on the fundamental dimensions given above, demonstrating all steps necessary for a completely functional system. First, we simply define a unit systemthat includes type definitions for commonly used units:[test_system_snippet_6]The macro [___BOOST_UNITS_STATIC_CONSTANT] is provided in [headerref boost/units/static_constant.hpp] to facilitate ODR- and thread-safe constant definition in header files. We then define some constants for the supported units to simplify variable definitions:[test_system_snippet_7]If support for textual output of units is desired, we can also specialize the [___base_unit_info] class for each fundamental dimension tag:[test_system_snippet_8]and similarly for `kilogram_base_unit` and `second_base_unit`. A future version of the library will provide a more flexible systemallowing for internationalization through a facet/locale-type mechanism. The `name()` and `symbol()` methods of [___base_unit_info] provide full and short names for the base unit. With these definitions, we have the rudimentary beginnings of our unit system, which can be used to determine reduced dimensions for arbitrary unit calculations.[endsect][section Scaled Base Units]Now, it is also possible to define a base unit as being a multiple ofanother base unit. For example, the way that `kilogram_base_unit` isactually defined by the library is along the following lines struct gram_base_unit : boost::units::base_unit<gram_base_unit, mass_dimension, 1> {}; typedef scaled_base_unit<gram_base_unit, scale<10, static_rational<3> > > kilogram_base_unit;This basically defines a kilogram as being 10^3 times a gram.There are several advantages to this approach.* It reflects the real meaning of these units better than treating them as independent units.* If a conversion is defined between grams or kilograms and some other units, it will automatically work for both kilograms and grams, with only one specialization.* Similarly, if the symbol for grams is defined as "g", then the symbol for kilograms will be "kg" without any extra effort.[endsect][section Scaled Units]We can also scale a [___unit] as a whole, rather than scaling the individualbase units which comprise it. For this purpose, we use the metafunction[___make_scaled_unit]. The main motivation for this feature is the metricprefixes defined in [headerref boost/units/systems/si/prefixes.hpp].A simple example of its usage would be.
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -