Boost logo

Boost :

From: Matthias Schabel (boost_at_[hidden])
Date: 2007-01-15 23:23:44

Hi Andrey -

> I haven't read any docs or seen the library. Just a thought on spot.
> May be a cast-like synax would be more natural here?
> quantity< double, SI::length > q1 = quantity_cast< SI::length >(1.5);
> quantity< int, SI::length > q2 = quantity_cast< SI::length >(100);

I like the idea of quantity_cast, being partial to making anything
potentially dangerous
be easily identified in code - I think a similar syntax could be used
for three different use cases:

1) construction from a value_type:

template<class Y,class Unit>
quantity_cast(const Y&);

2) casting to a different value_type:

template<class Y,class Z,class Unit>
quantity_cast(const quantity<Z,Unit>&)

and 3) casting to a different unit system

template<class Y,class System1,class System2,class Dim>
quantity<Y,unit<System2,Dim> >
quantity_cast(const quantity<Y,unit<System1,Dim> >&)

This should be relatively easy to implement...(famous last words)

> And construction with no explicit casting but via explicit constructor
> should be possible too:
> quantity< double, SI::length > q1(1.5);
> quantity< int, SI::length > q2(100);

My paradigm in designing this library is to be able to 1) prevent the
Mars Climate Orbiter disasters and
2) to facilitate changing of unit systems in code with maximal
safety. My concern with having an explicit
constructor with only a value_type argument is that someone who
decided to change from SI to CGS systems
could easily forget to update the constructor arguments :

quantity<double,SI::length> q1(1.0); // 1 meter

would get changed to

quantity<double,CGS::length> q1(1.0); // 1 centimeter

with no indication that there was any problem. If we allow explicit
unit system conversion, this change would
behave as expected:

quantity<double,SI::length> q1(1.0*meter); // 1 meter


quantity<double,CGS::length> q1(1.0*meter); // 100 centimeters

and, therefore, be safe. The same is true if we require quantity_cast
for unit system conversion.

> And this IMO should go implicitly:
> // Conversion from int to double via assignment
> q1 = q2;

I'm not a big lover of implicit type conversion. This is again an
issue of maximizing the safety of using quantities. If we allow
implicit value_type conversions, we permit truncation in cases of
things like double->int. Preventing this does add one more layer of
safety netting. On the other hand, there is something to be said for
having quantities simply delegate their value_type conversions to the
value_type itself - I guess I'm happy to go either way, depending on
the consensus...

> And quantity conversion should require explicit casting:
> quantity< double, SI::centigrade > q4;
> quantity< double, SI::kelvin > q5;
> q5 = quantity_cast< SI::kelvin >(q4);

Of course, the centigrade<->kelvin issue opens a new can of worms
since that conversion is affine, not linear. At present,
this conversion is not implemented in the library. My preference
would be to define a value_type that models a unit with offset that
could be converted to linear value_types... Right now, the library
allows implicit unit system conversions (as described above), and,
with quantity_cast, would allow casting as well.

> PS: And another couple of cents. Maybe the representation type of
> "quantity" template should be optional defaulted to double or, the
> better way, to the type that is natural for the quantity type. I.e.,
> for "SI::length" the "double" would be natural.

Paul Bristow has brought this up, too. I really, really wish there
was a template typedef facility. Lacking that, I'm inclined to
define, in the boost::units::SI namespace, another quantity class
that defaults to the SI system and double precision value_type. This
could invert the order of template arguments, too:

namespace SI {

template<class Unit,class Y = double> class quantity : public
boost::units::quantity<Y,Unit> { ... };


Thanks for the input.


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