Boost C++ Libraries Home Libraries People FAQ More

PrevUpHomeNext

FAQ

How does one distinguish between quantities that are physically different but have the same units (such as energy and torque)?
Angles are treated as units
Why are there homogeneous systems? Aren't heterogeneous systems sufficient?
Why can't I construct a quantity directly from the value type?
Why are conversions explicit by default?

Because Boost.Units includes plane and solid angle units in the SI system, torque and energy are, in fact, distinguishable (see torque). In addition, energy is a true scalar quantity, while torque, despite having the same units as energy if plane angle is not included, is in fact a pseudovector. Thus, a value type representing pseudovectors and encapsulating their algebra could also be implemented.

There are, however, a few SI units that are dimensionally indistinguishable within the SI system. These include the becquerel, which has units identical to frequency (Hz), and the sievert, which is degenerate with the gray. In cases such as this, the proper way to treat this difference is to recognize that expanding the set of base dimensions can provide disambiguation. For example, adding a base dimension for radioactive decays would allow the becquerel to be written as decays/second, differentiating it from the signature of hertz, which is simply 1/second.

If you don't like this, you can just ignore the angle units and go on your merry way (periodically screwing up when a routine wants degrees and you give it radians instead...)

Consider the following code:

cout << asin(sin(90.0 * degrees));

What should this print? If only heterogeneous systems are available it would print 1.5708 rad Why? Well, sin would return a quantity<dimensionless> effectively losing the information that degrees are being used. In order to propogate this extra information we need homogeneous systems.

This only breaks generic code--which ought to break anyway. The only literal value that ought to be converted to a quantity by generic code is zero, which should be handled by the default constructor. In addition, consider the search and replace problem allowing this poses:

quantity<si::length>    q(1.0);

Here, the intent is clear - we want a length of one in the SI system, which is one meter. However, imagine some well-intentioned coder attempting to reuse this code, but to have it perform the calculations in the CGS unit system instead. After searching for si:: and replacing it with cgs:: , we have:

quantity<cgs::length>	q(1.0);

Unfortunately, the meaning of this statement has suddenly changed from one meter to one centimeter. In contrast, as implemented, we begin with:

quantity<si::length>	q(1.0*si::meter);

and, after search and replace:

quantity<cgs::length>	q(1.0*cgs::meter);

which gives us an error. Even if the code has a @using namespace boost::units::si; declaration, the latter is still safe, with:

using namespace boost::units::si;
quantity<length>	q(1.0*meter);

going to

using namespace boost::units::cgs;
quantity<length>	q(1.0*meter);

The latter will involve an explicit conversion from meters to centimeters, but the value remains correct.

Safety and the potential for unintended conversions leading to precision loss and hidden performance costs. Options are provided for forcing implicit conversions between specific units to be allowed.


PrevUpHomeNext