📄 units.qbk
字号:
typedef make_scaled_unit<si::time, scale<10, static_rational<-9> > >::type nanosecond;nanosecond is a specialization of [___unit], and can beused in a quantity normally. quantity<nanosecond> t(1.0 * si::seconds); std::cout << t << std::endl; // prints 1e9 ns[endsect][endsect][section:Quantities Quantities]A *quantity* is defined as a value of an arbitrary value type that is associated with a specific unit. For example,while meter is a unit, 3.0 meters is a quantity. Quantities obey two separate algebras: the native algebra for their value type, and the dimensional analysis algebra for the associated unit. In addition, algebraic operations are definedbetween units and quantities to simplify the definition of quantities; it is effectively equivalent to algebra witha unit-valued quantity.Quantities are implemented by the [___quantity] template class defined in [headerref boost/units/quantity.hpp] : template<class Unit,class Y = double> class quantity;This class is templated on both unit type (`Unit`) and value type (`Y`), with the latter defaulting to double-precisionfloating point if not otherwise specified. The value type must have a normal copy constructor and copyassignment operator. Operators +, -, *, and / are provided for algebraic operations between scalars and units, scalars and quantities, units and quantities, and between quantities. In addition, integral andrational powers and roots can be computed using the [___pow]<R> and [___root]<R> functions. Finally, the standard set of boolean comparison operators ( `==, !=, <, <=, >, and >=` ) are provided to allow comparison of quantities from the same unit system. All operators simply delegate to thecorresponding operator of the value type if the units permit.[section:Heterogeneous_Operators Heterogeneous Operators]For most common value types, the result type of arithmetic operators is the same as the value type itself. For example, the sum of two double precision floating point numbers is another double precision floating point number. However, there are instances where this is not the case. A simple example is given by the [@http://en.wikipedia.org/wiki/Natural_number natural numbers] where the operator arithmetic obeys the following rules (using the standard notation for [@http://en.wikipedia.org/wiki/Number number systems]):* [$../../libs/units/images/form_12.png]* [$../../libs/units/images/form_13.png]* [$../../libs/units/images/form_14.png]* [$../../libs/units/images/form_15.png]This library is designed to support arbitrary value type algebra for addition, subtraction, multiplication, division, and rational powers and roots. It uses Boost.Typeof to deduce the result of these operators. For compilers thatsupport `typeof`, the appropriate value type will be automatically deduced. For compilers that do not providelanguage support for `typeof` it is necessary to register all the types used. For the case of natural numbers,this would amount to something like the following: BOOST_TYPEOF_REGISTER_TYPE(natural); BOOST_TYPEOF_REGISTER_TYPE(integer); BOOST_TYPEOF_REGISTER_TYPE(rational);[endsect][section:Conversions Conversions]Conversion is only meaningful for quantities as it implies the presence of at least a multiplicative scale factor and, possibly, and affine linear offset.Macros for simplifying the definition of conversions between units can be found in[headerref boost/units/conversion.hpp] and [headerref boost/units/absolute.hpp](for affine conversions with offsets). The macro [___BOOST_UNITS_DEFINE_CONVERSION_FACTOR] specifies a scalefactor for conversion from the first unit type to the second. Thefirst argument must be a [___base_unit]. The second argumentcan be either a [___base_unit] or a [___unit].Let's declare a simple base unit: struct foot_base_unit : base_unit<foot_base_unit, length_dimension, 10> { };Now, we want to be able to convert feet to meters and vice versa. The footis defined as exactly 0.3048 meters, so we can write the following BOOST_UNITS_DEFINE_CONVERSION_FACTOR(foot_base_unit, meter_base_unit, double, 0.3048);Alternately, we could use the SI length `typedef`: BOOST_UNITS_DEFINE_CONVERSION_FACTOR(foot_base_unit, SI::length, double, 0.3048);Since the SI unit of length is the meter, these two definitions are equivalent.If these conversions have been defined, then converting betweenscaled forms of these units will also automatically work.The macro [___BOOST_UNITS_DEFAULT_CONVERSION] specifies a conversionthat will be applied to a base unit when no direct conversion ispossible. This can be used to make arbitrary conversions workwith a single specialization: struct my_unit_tag : boost::units::base_unit<my_unit_tag, boost::units::force_type, 1> {}; // define the conversion factor BOOST_UNITS_DEFINE_CONVERSION_FACTOR(my_unit_tag, SI::force, double, 3.14159265358979323846); // make conversion to SI the default. BOOST_UNITS_DEFAULT_CONVERSION(my_unit_tag, SI::force);[endsect][section:Quantity_Construction_and_Conversion Construction and Conversion of Quantities]This library is designed to emphasize safety above convenience when performing operations with dimensioned quantities.Specifically, construction of quantities is required to fully specify both value and unit. Direct construction from a scalar valueis prohibited (though the static member function [___from_value] is provided to enable this functionality where it is necessary. In addition, a [___quantity_cast] to a reference allows direct access to the underlying value of a [___quantity] variable. An explicit constructor is provided to enable conversion betweendimensionally compatible quantities in different unit systems. Implicit conversions between unit systems areallowed only when the reduced units are identical, allowing, for example, trivial conversions betweenequivalent units in different systems (such as SI seconds and CGS seconds) while simultaneously enablingunintentional unit system mismatches to be caught at compile time and preventing potential loss of precision andperformance overhead from unintended conversions. Assignment follows the same rules.An exception is made for quantities for which the unit reduces to dimensionless; in this case, implicit conversionto the underlying value type is allowed via class template specialization. Quantities of different value types are implicitly convertible only if the value types are themselves implicitly convertible. The [___quantity] class also definesa `value()` member for directly accessing the underlying value.To summarize, conversions are allowed under the following conditions :* implicit conversion of `quantity<Unit,Y>` to `quantity<Unit,Z>` is allowed if `Y` and `Z` are implicitly convertible.* assignment between `quantity<Unit,Y>` and `quantity<Unit,Z>` is allowed if `Y` and `Z` are implicitly convertible.* explicit conversion between `quantity<Unit1,Y>` and `quantity<Unit2,Z>` is allowed if `Unit1` and `Unit2` have the same dimensions and if `Y` and `Z` are implicitly convertible.* implicit conversion between `quantity<Unit1,Y>` and `quantity<Unit2,Z>` is allowed if `Unit1` reduces to exactly the same combination of base units as `Unit2` and if `Y` and `Z` are convertible.* assignment between `quantity<Unit1,Y>` and `quantity<Unit2,Z>` is allowed under the same conditions as implicit conversion.* `quantity<Unit,Y>` can be directly constructed from a value of type `Y` using the static member function [___from_value]. Doing so, naturally, bypasses any type-checking of the newly assigned value, so this method should be used only when absolutely necessary.Of course, any time implicit conversion is allowed, an explicit conversion isalso legal.Because dimensionless quantities have no associated units, they behave as normal scalars, and allow implicit conversion to and from the underlying value type or types that are convertible to/from that value type.[endsect][endsect][section:Examples Examples][section:DimensionExample Dimension Example]([@../../libs/units/example/dimension.cpp dimension.cpp])By using MPL metafunctions and the template specializations for operations on composite dimensions(defined in [headerref boost/units/dimension.hpp]) it is possible to perform compile time arithmeticaccording to the dimensional analysis rules described [link boost_units.Dimensional_Analysis above]to produce new composite dimensions :[import ../example/dimension.cpp][dimension_snippet_1]outputting (with symbol demangling, implemented in [headerref boost/units/detail/utility.hpp])[dimension_output][endsect][section:UnitExample Unit Example]([@../../libs/units/example/unit.cpp unit.cpp])This example demonstrates the use of the simple but functional unit system implemented in [headerref libs/units/example/test_system.hpp] :[import ../example/unit.cpp][unit_snippet_1]We can perform various algebraic operations on these units, resulting in the following output:[unit_output][endsect][section:QuantityExample Quantity Example]([@../../libs/units/example/quantity.cpp quantity.cpp])This example demonstrates how to use quantities of our toy unit system :[import ../example/quantity.cpp][quantity_snippet_1]giving us the basic quantity functionality :[quantity_output_double]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 ofcomplex lengths and energies) :[quantity_snippet_2]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 :[quantity_output_complex][endsect][section:KitchenSinkExample Kitchen Sink Example]([@../../libs/units/example/kitchen_sink.cpp 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 [headerref boost/units/systems/si.hpp].If we define a few units and associated quantities,[import ../example/kitchen_sink.cpp][kitchen_sink_snippet_1]the various algebraic operations between scalars, units, and quantities give [kitchen_sink_output_1]Scalar/unit operations :[kitchen_sink_output_2]Unit/unit operations and integral/rational powers of units :[kitchen_sink_output_3]Scalar/quantity operations :[kitchen_sink_output_4]Unit/quantity operations :[kitchen_sink_output_5]Quantity/quantity operations and integral/rational powers of quantities :[kitchen_sink_output_6]Logical comparison operators are also defined between quantities :[kitchen_sink_snippet_2]giving[kitchen_sink_output_7]Implicit conversion is allowed between dimensionless quantities and their corresponding value types :[kitchen_sink_snippet_3]A generic function for computing mechanical work can be defined that takes force and distance argumentsin an arbitrary unit system and returns energy in the same system:[kitchen_sink_function_snippet_3][kitchen_sink_snippet_4]which functions as expected for SI quantities :[kitchen_sink_output_9]The ideal gas law can also be implemented in SI units :[kitchen_sink_function_snippet_4][kitchen_sink_snippet_5]with the resulting output :[kitchen_sink_output_10]Trigonometric and inverse trigonometric functions can be implemented for any unit systemthat provides an angular base dimension. For radians, these functions are found in [headerref boost/units/cmath.hpp] These behave as one expects, with trigonometric functionstaking an angular quantity and returning a dimensionless quantity, while the inverse trigonometric functionstake a dimensionless quantity and return an angular quantity :Defining a few angular quantities,[kitchen_sink_snippet_6]yields[kitchen_sink_output_11]Dealing with complex quantities is trivial. Here is the calculation of complex impedance :[kitchen_sink_snippet_7]giving[kitchen_sink_output_12][section:UDT_Quantities User-defined value types]User-defined value types that support the appropriate arithmetic operations are automatically supportedas 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 overloadingthe [___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 anddemonstrates its use as a quantity value type; the full code is found in [@../../libs/units/example/measurement.hpp measurement.hpp].Then, defining some `measurement` [___quantity] variables[kitchen_sink_snippet_8]gives[kitchen_sink_output_13]If we implement the overloaded helper classes for rational powers and rootsthen we can also compute rational powers of measurement quantities :[kitchen_sink_output_14][endsect][endsect][section:ConversionExample Conversion Example]([@../../libs/units/example/conversion.cpp conversion.cpp])This example demonstrates the various allowed conversions between SI and CGS units. Defining somequantities[import ../example/conversion.cpp][conversion_snippet_1]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 treatedas an explicit conversion because there is no way to emulate the exact behavior of the built-inconversion. Explicit constructors allow conversions for two cases:* explicit casting of a [___quantity] to a different `value_type` :[conversion_snippet_3]* and explicit casting of a [___quantity] to a different unit :[conversion_snippet_4]
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -