Boost logo

Boost :

From: Beth Jacobson (bethj_at_[hidden])
Date: 2006-06-22 15:34:03

David Walthall wrote:

> Oleg Abrosimov wrote:
>> Actually, my question is:
>> Can you provide good reasons to follow current PQS style (length::m
>> etc.) instead of simply Length, as me and others have proposed?
> I can think of a couple. Here is a rather contrived one:
> pqs::length universe_radius = 1.4e26 * METER;
> pqs::volume universe_volume =
> (4.0/3.0) * M_PI * pqs::pow<3>(universe_radius);
> You now have 2.744e78 m^3, which could overflow if the maximum exponent
> of the double on your system is +37. As I said, that was contrived, but
> embedded systems may not have a large maximum exponent for doubles.

Under/overflow will certainly be an issue for some people if they can't
specify their own base units, but I don't know if a tight coupling
between units and dimensions is the best solution. Could there be
some sort of global setting (a facet, maybe?) where we could specify
units for base dimensions for the entire application?

> The layer that I work on has to collect data
> from several legacy application outputs that use different underlying
> systems of units. One gives data in kJ and another gives data in kcal.
> Rather than having to constantly convert between the two values, which
> is error prone, I simply write:
> // Prototypes of interface with two different legacy codes
> pqs::energy::kJ GetLegacyData1(/*args*/);
> pqs::energy::kcal GetLegacyData2(/*args*/);
> // used in my program
> pqs::energy::kJ = GetLegacyData1() + GetLegacyData2();

Another example would be something like this (excuse the psuedo-pqs):

pqs::pressure::psi WaterPressure(pqs::length::feet depth)
    const pqs::length_per_pressure::foot_per_psi pressureRatio(2.31);
    return depth/pressureRatio;

If units weren't specified in the function declaration, it could be
called with the wrong ones, and its return value would be garbage.

Both your example and mine have a common element though. They both
involve moving between numeric values and dimensions. I can't think of
an instance where units would be useful when that isn't the case. If
that's true, then it seems like overkill to require bound units
throughout the program. A simpler solution would be to prohibit
dimension variables from being assigned or returning "raw" numbers. The
only way to get or set a value would be through unit functions like this

    pqs::energy energyVal = pqs::kcal(value);

My water pressure example would look like this

    pqs::pressure WaterPressure(pqs::length depth)
       const pqs::length_per_pressure ratio(pqs::foot_per_psi(2.31));
       return depth/ratio;

The value, 2.31, would be converted to the global units, whatever they
happened to be, so the function would work with any unit system. Since
units would be specified at the point of conversion, this method might
even be a little safer. In pqs, you might do something like this

    pqs::length::m depth;

    // lots of code

    double depthAsDouble(depth);
    SetFieldValue("DepthInFt", depthAsDouble);

    cout << "Enter new depth (in feet): "
    cin >> depth;

Because depth is declared far from where it's output and reassigned,
these mistakes would be easy to miss. But if the code worked like this

    pqs::length depth;

    // lots of code

    // Must use units function to convert to double
    double depthAsDouble = pqs::feet(depth);
    SetFieldValue("DepthInFt", depthAsDouble);

    cout << "Enter new depth (in feet): "
    // Must use units function to convert from double
    cin >> depthAsDouble;
    depth = pqs::feet(depthAsDouble);

The programmer would have to declare the units at the point where
they're used. This wouldn't eliminate mistakes altogether, but it might
discourage the more obvious ones.

The biggest advantage of all this is that units would no longer be an
integral part of the dimensions library, and the only difference between
the unitless and unitful versions of the library would be in how values
are assigned to and extracted from dimension variables.

Boost list run by bdawes at, gregod at, cpdaniel at, john at