We define a 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 identical reduced 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 template<class Dim,class System> class unit;
In addition to supporting the compile-time dimensional analysis operations,
the +, -, *, and / runtime operators are provided for 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 system that includes type definitions for commonly used units:
struct meter_base_unit : base_unit<meter_base_unit, length_dimension, 1> { }; struct kilogram_base_unit : base_unit<kilogram_base_unit, mass_dimension, 2> { }; struct second_base_unit : base_unit<second_base_unit, time_dimension, 3> { }; typedef make_system< meter_base_unit, kilogram_base_unit, second_base_unit>::type mks_system; /// unit typedefs typedef unit<dimensionless_type,mks_system> dimensionless; typedef unit<length_dimension,mks_system> length; typedef unit<mass_dimension,mks_system> mass; typedef unit<time_dimension,mks_system> time; typedef unit<area_dimension,mks_system> area; typedef unit<energy_dimension,mks_system> energy;
The macro
/// unit constants BOOST_UNITS_STATIC_CONSTANT(meter,length); BOOST_UNITS_STATIC_CONSTANT(meters,length); BOOST_UNITS_STATIC_CONSTANT(kilogram,mass); BOOST_UNITS_STATIC_CONSTANT(kilograms,mass); BOOST_UNITS_STATIC_CONSTANT(second,time); BOOST_UNITS_STATIC_CONSTANT(seconds,time); BOOST_UNITS_STATIC_CONSTANT(square_meter,area); BOOST_UNITS_STATIC_CONSTANT(square_meters,area); BOOST_UNITS_STATIC_CONSTANT(joule,energy); BOOST_UNITS_STATIC_CONSTANT(joules,energy);
If support for textual output of units is desired, we can also specialize
the
template<> struct base_unit_info<test::meter_base_unit> { static std::string name() { return "meter"; } static std::string symbol() { return "m"; } };
and similarly for
Now, it is also possible to define a base unit as being a multiple of another
base unit. For example, the way that 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.
We can also scale a A simple example of its usage would be. typedef make_scaled_unit<si::time, scale<10, static_rational<-9> > >::type nanosecond;
nanosecond is a specialization of quantity<nanosecond> t(1.0 * si::seconds); std::cout << t << std::endl; // prints 1e9 ns |