
Oh, okay, missed that. So I probably don't fully understand what the units library is doing but I find this behavior a bit worrisome.
[kbelco@wsblade001 ~]$ cat test3.cpp
int main(int, char **) { quantity<fahrenheit::temperature> f(212 * fahrenheit::temperature()); quantity<celsius::temperature> c(f); std::cout << f << std::endl; std::cout << c << std::endl; return 0; }
[kbelco@wsblade001 ~]$ ./a.out 212 F 117.778 C
If 'f' is 212ºF, why, when converting it to ºC, do I end up at 117 and change? Is this really what we should expect? It seems that this very simple use case produces unexpected, and to a casual user wrong, results. I understand the need for complexity but it seems to show up very early in the user experience.
Because a temperature change of 212ºF is equal to a temperature change of 117.778ºC = (5/9)*212. What would you expect the following to do: int main(int, char **) { quantity<fahrenheit::temperature> f(32*fahrenheit::temperature()); quantity<celsius::temperature> c(0*celsius::temperature()); std::cout << 2.*f << std::endl; std::cout << 2.*c << std::endl; std::cout << f+quantity<fahrenheit::temperature>(c) << std::endl; std::cout << quantity<celsius::temperature>(f)+c << std::endl; return 0; } ? What does multiplying an absolute temperature by 2 mean? Should the last two lines give me 32+32 = 64 and 0+0 = 0? Why would the order of conversion matter? I understand the desire for temperature to equate to the common interpretation, but this approach quickly becomes problematic when you allow arithmetic operations. The same issue arises in std::chrono in differentiating between specific time points and durations. If you want a temperature point, use quantity< absolute<fahrenheit::temperature> >. This will have the added benefit of allowing conversions but disallowing operations that don't make sense... Some code: #include <iostream> #include <boost/units/absolute.hpp> #include <boost/units/systems/temperature/celsius.hpp> #include <boost/units/systems/temperature/fahrenheit.hpp> #include <boost/units/systems/si/temperature.hpp> #include <boost/units/base_units/temperature/conversions.hpp> using namespace boost::units; int main() { quantity<celsius::temperature> dTC(10.*celsius::temperature()); quantity<fahrenheit::temperature> dTF(10.*fahrenheit::temperature()); quantity<si::temperature> dTK(10.*si::kelvin); std::cout << dTC << std::endl; std::cout << dTF << std::endl; std::cout << dTK << std::endl; quantity<absolute<celsius::temperature> > TC(0*absolute<celsius::temperature>()); quantity<absolute<fahrenheit::temperature> > TF(32.*absolute<fahrenheit::temperature>()); quantity<absolute<si::temperature> > TK(0.*absolute<si::temperature>()); std::cout << TC << std::endl; std::cout << TF << std::endl; std::cout << TK << std::endl; std::cout << quantity<absolute<celsius::temperature> >(TF) << std::endl; std::cout << quantity<absolute<celsius::temperature> >(TK) << std::endl; std::cout << quantity<absolute<fahrenheit::temperature> >(TC) << std::endl; std::cout << quantity<absolute<fahrenheit::temperature> >(TK) << std::endl; // std::cout << TC+quantity<absolute<celsius::temperature> >(TF) << std::endl; // fails because you cannot add two absolute temperatures std::cout << TC+quantity<celsius::temperature>(dTF) << std::endl; std::cout << TF+quantity<fahrenheit::temperature>(dTC) << std::endl; return 0; } gives 10 C 10 F 10 K 0 absolute C 32 absolute F 0 absolute K 0 absolute C -273.15 absolute C 32 absolute F -459.67 absolute F 5.55556 absolute C 50 absolute F Essentially the design of Boost.Units emphasizes safety over convenience so, generally, if you can't do something it is a problem with your abstraction.