[units] unit conversion on construction in relation to argument passing
Hi, Boost.Units offers automatic conversion (if conversion factor is defined) on construction of variables: quantity<cgs::lengh> A = 4.*cgs::centimeter; quantity<si::length> a(A); nice! But for some reason I believe this would work for argument functions double f(quantity<si::length> v){ return 1.;} ... quantity<cgs::lengh> A = 4.*cgs::centimeter f(A); // doesn't work! not matching function why is this? isn't the argument of the call a sort of construction argument for the function argument, or is more like a plain assignment. Is there a way to force the automatic conversion of the function call. Or I am forced to use this other long call? f(quantity<si::length>(A)); Thanks Alfredo Full code: #include<boost/units/systems/si.hpp> #include<boost/units/systems/cgs.hpp> double f(quantity<si::length> v){ return 1.; } int main(){ quantity<cgs::length> A(4.*cgs::centimeter); f(A); //not matching function return 0; }
AMDG On 03/24/2011 10:04 PM, alfC wrote:
Hi, Boost.Units offers automatic conversion (if conversion factor is defined) on construction of variables:
quantity<cgs::lengh> A = 4.*cgs::centimeter; quantity<si::length> a(A);
nice! But for some reason I believe this would work for argument functions
double f(quantity<si::length> v){ return 1.;} ... quantity<cgs::lengh> A = 4.*cgs::centimeter f(A); // doesn't work! not matching function
why is this? isn't the argument of the call a sort of construction argument for the function argument, or is more like a plain assignment. Is there a way to force the automatic conversion of the function call.
Or I am forced to use this other long call?
f(quantity<si::length>(A));
Yes. The constructor is explicit. In Christ, Steven Watanabe
nice! But for some reason I believe this would work for argument functions
double f(quantity<si::length> v){ return 1.;} ... quantity<cgs::lengh> A = 4.*cgs::centimeter f(A); // doesn't work! not matching function
why is this? isn't the argument of the call a sort of construction argument for the function argument, or is more like a plain assignment. Is there a way to force the automatic conversion of the function call.
Or I am forced to use this other long call?
f(quantity<si::length>(A));
Yes. The constructor is explicit.
Or you can write it as a template function that takes any argument that is a quantity of length : #include <iostream> #include <boost/units/io.hpp> #include <boost/units/systems/cgs.hpp> #include <boost/units/systems/si.hpp> using namespace boost::units; template<class System,class Y> Y f(quantity<unit<length_dimension,System>,Y> v) { const Y w = quantity<si::length,Y>(v).value(); std::cout << v << "\t" << w << std::endl; return w; } int main(void) { f(quantity<cgs::length,double>(17.0*cgs::centimeters)); return 0; } Matthias
On Mar 25, 9:46 am, Matthias Schabel <bo...@schabel-family.org> wrote:
nice! But for some reason I believe this would work for argument functions
double f(quantity<si::length> v){ return 1.;} ... quantity<cgs::lengh> A = 4.*cgs::centimeter f(A); // doesn't work! not matching function
why is this? isn't the argument of the call a sort of construction argument for the function argument, or is more like a plain assignment. Is there a way to force the automatic conversion of the function call.
Or I am forced to use this other long call?
f(quantity<si::length>(A));
Yes. The constructor is explicit.
thanks for the clarification
Or you can write it as a template function that takes any argument that is a quantity of length : [...code...]
Thank you for the suggestion, the problem is that a nice looking function such as void f( quantity<volume> v, quantity<temperature> t, quantity<length> l ){ ... use v, l, t in a given controlled set of units } transfroms into this mess, template< class VolumeUnit, class TemperatureUnit, class LengthUnit
void f( quantity<VolumeUnit> v_, quantity<TemperatureUnit> t_, quantity<LengthUnit> l_ ){ quantity<volume> v(v); quantity<temperature> t(t_); quantity<length> l(l_); ... use v, l, t in a given controlled set of unit }
just to obtain the same effect. and that without even static asserting that XXXUnit is_unit. For sometime I agreed that implicit construction was a bad idea because of uncontrolled unit conversion but in the light of the applications (i.e. real life code) I now think that it can be a good idea instead. The uncontrolled conversion can still be tamed by the (un)definition of conversion factors.
On 3/25/2011 10:40 AM, alfC wrote:
On Mar 25, 9:46 am, Matthias Schabel<bo...@schabel-family.org> wrote:
nice! But for some reason I believe this would work for argument functions
double f(quantity<si::length> v){ return 1.;} ... quantity<cgs::lengh> A = 4.*cgs::centimeter f(A); // doesn't work! not matching function
why is this? isn't the argument of the call a sort of construction argument for the function argument, or is more like a plain assignment. Is there a way to force the automatic conversion of the function call.
Or I am forced to use this other long call?
f(quantity<si::length>(A));
Yes. The constructor is explicit.
thanks for the clarification
Or you can write it as a template function that takes any argument that is a quantity of length : [...code...]
Thank you for the suggestion, the problem is that a nice looking function such as
void f( quantity<volume> v, quantity<temperature> t, quantity<length> l ){ ... use v, l, t in a given controlled set of units }
transfroms into this mess,
template< class VolumeUnit, class TemperatureUnit, class LengthUnit
void f( quantity<VolumeUnit> v_, quantity<TemperatureUnit> t_, quantity<LengthUnit> l_ ){ quantity<volume> v(v); quantity<temperature> t(t_); quantity<length> l(l_); ... use v, l, t in a given controlled set of unit }
just to obtain the same effect. and that without even static asserting that XXXUnit is_unit.
Not usually. If your equations are dimensionally coherent, and not empirical, you can generally do without a lot of what you just showed. For example, one might be tempted to write the head/pressure conversion as: quantity<si::pressure> head_to_press( quantity<si::length> head , quantity<si::mass_density> den ) { quantity<si::acceleration> g = 9.80665 * si::meters_per_second_squared return head * den * g; } All you really need to do though is: template < typename System, typename T > quantity< unit<pressure_dimension, T > head_to_press( quantity< unit<length_dimension, System>, T> head , quantity< unit<mass_density_dimension, System>, T> den ) { quantity< unit<acceleration_dimension, System>, T> g(9.8066 * si::meters_per_second_squared); return head * den * g; } The only part you have to do explicit conversions on is your constants. Of course, when dealing with empirical equations you've got a different thing going on. More often than not you have to break out of the units anyway and use the "unsafe" operations like ::from_value.
participants (4)
-
alfC
-
Matthias Schabel
-
Noah Roberts
-
Steven Watanabe