
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 ----------------------------------------------------------------