Boost logo

Boost :

From: Matthias Schabel (boost_at_[hidden])
Date: 2007-01-16 21:29:26


Hi Andrey -

> IMHO, such implicit conversions would be more natural for users (for
> me at least). Of course, such conversions should be valid only if
> these representation types are implicitly convertible (a user may
> ensure they are not, if it's necessary). And if there is a percision
> loss on such conversion, a well-mannered compiler will issue a
> warning.

OK, I have implicit value_type conversion implemented for the next
release. I've
also flipped the order of template parameters in quantity and added
double as
a default value_type...everything seems to work as before, but now
you can write

quantity<SI::length> q1(1.5*SI::meters);

etc...

> My humble knowledge may have confused me but I thought that the same
> temperature by Centigrade and by Kelvin will always differ by about
> 273 (i.e. the conversion is linear). Which is not right in case of
> Farenheit.

What I mean by linear vs. affine is that, while the scale factor for
converting
temperature differences in Kelvin to/from centigrade is one, there is
a nonzero
translation of the origin (MathWorld has a good description of linear
and affine
transformations):

http://mathworld.wolfram.com/LinearTransformation.html
http://mathworld.wolfram.com/AffineTransformation.html

The point that Ben was making in his post is that, while absolute
temperature
conversion between Kelvin and centigrade requires an offset,
conversion of
temperature differences does not. As far as I can tell, to integrate
this directly
into the library would require strong coupling between a special
value_type
flagging whether a quantity was an absolute temperature or a
difference, which
I think is undesirable. By defining special value_types

class absolute_temperature;
class temperature_difference;

and defining the operators between these so that you can add or subtract
temperature_differences to/from absolute_temperatures to get another
absolute_temperature, add or subtract two temperature_differences to get
another temperature difference, and subtract two
absolute_temperatures to
get a temperature_difference you should be able to get the correct
behavior.
Maybe I'll try to put together a quick example of this...

> Maybe the library should offer an opportunity to extend the out of box
> set of supported quantities. If you agree with me here, there should
> be a way of specifying user-defined quantities and conversion rules
> between them. I see it something like this:

This already exists in the library; I'm changing the syntax a little
for the next release,
but there are basically two ways to control unit conversion:

1) if your unit system is "normal" - so that it doesn't require
special treatment of
the value to perform dimensional analysis on quantities - you can
just define
specializations of the convert_base_unit class for each fundamental unit
(length, time, etc..) for forward and inverse conversions:

template<>
struct convert_base_unit<length_tag,SI::system,CGS::system>
{
        template<class Y> static Y factor() { return Y(100); }
};

template<>
struct convert_base_unit<length_tag,CGS::system,SI::system>
{
        template<class Y> static Y factor() { return Y(0.01); }
};

2) if you need more radical surgery, all conversions are mediated by the
conversion_helper class, so explicit quantity conversion between unit
systems looks like this:

// explicit conversion from different unit system
template<class Y,
          class System,
          class Dim>
template<class System2,class Dim2>
quantity< Y,unit<System,Dim> >::quantity(const quantity<
Y,unit<System2,Dim2> >& source)
{
        *this = conversion_helper<System2,System>::convert_quantity(source);
}

where the default conversion_helper (in conversion.hpp)
implementation is a bit messy, but really just
goes through all the terms in the source unit, and determines and
accumulates the scale factors to get
a final scale factor for the conversion. If you specialize this for a
new unit system, you can pretty much
do anything you want here...

> Although the structures as the conversion rules is not the best way to
> implement it (making use of free functions for this purpose would be
> more flexible because of ADL involvement), the main idea is to extract
> the conversion algorithm to a user-defined entity.

Hmmm...I actually was having the opposite problem when trying to
implement quantity_cast : I could
get one overload to work for casting from a raw value_type, but the
overload implementing value_type
conversion wouldn't resolve...maybe I'm doing something dumb, but it
seems that the compiler isn't
recognizing that the typedef'd length is really
unit<SI::system,length_type>. Strange.

> As it was mentioned by Peder Holt, it is quite possible to make these
> template parameters irrelevant of the position. I'd do something like
> that:

[snip]

This looks interesting, although, as Janek pointed out, it only makes
sense to have a default type for the value_type,
so having arbitrary ordering of the template parameters doesn't seem
to provide much real benefit for the added
compile-time overhead. As always, I'm willing to be flexible if we
can come up with a convincing reason why this is
needed/desirable...

Thanks,

Matthias
----------------------------------------------------------------
Matthias Schabel, Ph.D.
Assistant Professor, Department of Radiology
Utah Center for Advanced Imaging Research
729 Arapeen Drive
Salt Lake City, UT 84108
801-587-9413 (work)
801-585-3592 (fax)
801-706-5760 (cell)
801-484-0811 (home)
matthias dot schabel at hsc dot utah dot edu
----------------------------------------------------------------


Boost list run by bdawes at acm.org, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk