[units] Dimensionless? expecting length+length

Hello, I am working on some trajectory calculations, and having a strange compiler error. First, great that I should get a compiler error at all! Second, what am I missing? quantity<acceleration> g() { static const auto gValue = static_cast<double>(9.812); static const auto metersPerSecondPerSecond = meters / second / second; static const quantity<acceleration> g = gValue*metersPerSecondPerSecond; return g; } double Class1::CalculateZeta(double timeMilliseconds, double heightMeters) { static const auto two = static_cast<double>(2); static const auto milliseconds = milli*seconds; const auto t = timeMilliseconds*milliseconds; const auto h = heightMeters*meters; const auto g_ = g(); auto result = -(g_ / two)*(t*t) + h; return result.value(); } Just if I did the dimensional analysis, I might expect the time components (i.e. T^2) to cancel themselves out, which should leave me with length+length, no? This is exposed via a C++ CLR (VS2013), but the Boost.Units are done internally. What am I missing here? I need to normalize the units, say to meters, etc? Best regards, Michael Powell Errors: Error 4 error C2676: binary '+' : 'boost::units::quantity<boost::units::unit<boost::units::list<boost::units::dim<Derived,boost::units::static_rational<1,1>>,boost::units::dimensionless_type>,boost::units::heterogeneous_system<boost::units::heterogeneous_system_impl<boost::units::list<boost::units::heterogeneous_system_dim<boost::units::si::meter_base_unit,boost::units::static_rational<1,1>>,boost::units::dimensionless_type>,boost::units::list<boost::units::dim<Derived,boost::units::static_rational<1,1>>,boost::units::dimensionless_type>,boost::units::list<boost::units::scale_list_dim<Scale>,boost::units::dimensionless_type>>>,void>,double>' does not define this operator or a conversion to a type acceptable to the predefined operator I:\Source\Spikes\Kingdom.Physics\src\Kingdom.Physics.Calculators\Class1.cpp 43 1 Kingdom.Physics.Calculators Error 2 error C2784: 'add_typeof_helper<boost::units::unit<Dim1,System1,void>,boost::units::unit<Dim2,System2,void>>::type boost::units::operator +(const boost::units::unit<Dim1,System1,void> &,const boost::units::unit<Dim2,System2,void> &)' : could not deduce template argument for 'const boost::units::unit<Dim1,System1,void> &' from 'boost::units::quantity<boost::units::unit<boost::units::list<boost::units::dim<Derived,boost::units::static_rational<1,1>>,boost::units::dimensionless_type>,boost::units::heterogeneous_system<boost::units::heterogeneous_system_impl<boost::units::list<boost::units::heterogeneous_system_dim<boost::units::si::meter_base_unit,boost::units::static_rational<1,1>>,boost::units::dimensionless_type>,boost::units::list<boost::units::dim<Derived,boost::units::static_rational<1,1>>,boost::units::dimensionless_type>,boost::units::list<boost::units::scale_list_dim<Scale>,boost::units::dimensionless_type>>>,void>,double>' I:\Source\Spikes\Kingdom.Physics\src\Kingdom.Physics.Calculators\Class1.cpp 43 1 Kingdom.Physics.Calculators Error 3 error C2893: Failed to specialize function template 'add_typeof_helper<boost::units::quantity<Unit1,X>,boost::units::quantity<Unit2,Y>>::type boost::units::operator +(const boost::units::quantity<Unit1,X> &,const boost::units::quantity<Unit2,Y> &)' I:\Source\Spikes\Kingdom.Physics\src\Kingdom.Physics.Calculators\Class1.cpp 43 1 Kingdom.Physics.Calculators 5 IntelliSense: no operator "+" matches these operands operand types are: boost::units::quantity<boost::units::unit<boost::units::list<boost::units::dim<boost::units::length_base_dimension, boost::units::static_rational<1L, 1L>>, boost::units::dimensionless_type>, boost::units::heterogeneous_system<boost::units::heterogeneous_system_impl<boost::units::list<boost::units::heterogeneous_system_dim<boost::units::si::meter_base_unit, boost::units::static_rational<1L, 1L>>, boost::units::dimensionless_type>, boost::units::list<boost::units::dim<boost::units::length_base_dimension, boost::units::static_rational<1L, 1L>>, boost::units::dimensionless_type>, boost::units::list<boost::units::scale_list_dim<boost::units::scale<10L, boost::units::static_rational<-6L, 1L>>>, boost::units::dimensionless_type>>>, void>, double> + const boost::units::quantity<boost::units::unit<boost::units::length_dimension, boost::units::si::system, void>, double> i:\Source\Spikes\Kingdom.Physics\src\Kingdom.Physics.Calculators\Class1.cpp 43 49 Kingdom.Physics.Calculators

On 9/08/2015 10:27, Michael Powell wrote:
I am working on some trajectory calculations, and having a strange compiler error. First, great that I should get a compiler error at all! Second, what am I missing? [...] boost::units::quantity<boost::units::unit<boost::units::list<boost::units::dim<boost::units::length_base_dimension, boost::units::static_rational<1L, 1L>>, boost::units::dimensionless_type>, boost::units::heterogeneous_system<boost::units::heterogeneous_system_impl<boost::units::list<boost::units::heterogeneous_system_dim<boost::units::si::meter_base_unit, boost::units::static_rational<1L, 1L>>, boost::units::dimensionless_type>, boost::units::list<boost::units::dim<boost::units::length_base_dimension, boost::units::static_rational<1L, 1L>>, boost::units::dimensionless_type>, boost::units::list<boost::units::scale_list_dim<boost::units::scale<10L, boost::units::static_rational<-6L, 1L>>>, boost::units::dimensionless_type>>>, void>, double>
I believe this is the "problem" here -- there's a scale of 10^-6 applied, presumably as a result of multiplying with milliseconds twice. I've encountered issues before where some of the operators don't play nicely with scaled units. Try normalising the milliseconds to seconds before putting them in the rest of the formula. You should be able to do this simply by assigning them to a seconds quantity type instead of using "auto".

On Sun, Aug 9, 2015 at 7:40 PM, Gavin Lambert <gavinl@compacsort.com> wrote:
On 9/08/2015 10:27, Michael Powell wrote:
I am working on some trajectory calculations, and having a strange compiler error. First, great that I should get a compiler error at all! Second, what am I missing?
[...]
boost::units::quantity<boost::units::unit<boost::units::list<boost::units::dim<boost::units::length_base_dimension, boost::units::static_rational<1L, 1L>>, boost::units::dimensionless_type>,
boost::units::heterogeneous_system<boost::units::heterogeneous_system_impl<boost::units::list<boost::units::heterogeneous_system_dim<boost::units::si::meter_base_unit, boost::units::static_rational<1L, 1L>>, boost::units::dimensionless_type>, boost::units::list<boost::units::dim<boost::units::length_base_dimension, boost::units::static_rational<1L, 1L>>, boost::units::dimensionless_type>, boost::units::list<boost::units::scale_list_dim<boost::units::scale<10L, boost::units::static_rational<-6L, 1L>>>, boost::units::dimensionless_type>>>, void>, double>
I believe this is the "problem" here -- there's a scale of 10^-6 applied, presumably as a result of multiplying with milliseconds twice. I've encountered issues before where some of the operators don't play nicely with scaled units.
Sure.
Try normalising the milliseconds to seconds before putting them in the rest of the formula. You should be able to do this simply by assigning them to a seconds quantity type instead of using "auto".
I'm not sure what you mean, "seconds quantity type"? There would be quantity<time> ? Which one can assign from (time_value * seconds), to arrive at seconds? It is possible to build up a milliseconds unit, or possible a milliseconds_to_seconds "conversion factor" ?
_______________________________________________ Boost-users mailing list Boost-users@lists.boost.org http://lists.boost.org/mailman/listinfo.cgi/boost-users

On 11/08/2015 01:43, Michael Powell wrote:
Try normalising the milliseconds to seconds before putting them in the rest of the formula. You should be able to do this simply by assigning them to a seconds quantity type instead of using "auto".
I'm not sure what you mean, "seconds quantity type"?
There would be quantity<time> ?
Yes. I have this: typedef quantity<time> Time; And explicitly use "Time" as the type for all time-related results instead of using "auto".
Which one can assign from (time_value * seconds), to arrive at seconds?
It is possible to build up a milliseconds unit, or possible a milliseconds_to_seconds "conversion factor" ?
You can, but it's not necessary. Simply assign value * milli * seconds to a variable of quantity<time> (aka Time) and it automatically converts everything to seconds (since that's the base unit of "time"). This prevents other operations getting confused by scaled units, which happens when you use "auto" because it skips this conversion.

On August 10, 2015 10:06:43 EDT, Gavin Lambert <gavinl@compacsort.com> wrote:
Try normalising the milliseconds to seconds before putting them in
of the formula. You should be able to do this simply by assigning
On 11/08/2015 01:43, Michael Powell wrote: the rest them to a
seconds quantity type instead of using "auto".
I'm not sure what you mean, "seconds quantity type"?
There would be quantity<time> ?
Yes. I have this:
typedef quantity<time> Time;
And explicitly use "Time" as the type for all time-related results instead of using "auto".
Which one can assign from (time_value * seconds), to arrive at seconds?
It is possible to build up a milliseconds unit, or possible a milliseconds_to_seconds "conversion factor" ?
You can, but it's not necessary. Simply assign value * milli * seconds
to a variable of quantity<time> (aka Time) and it automatically converts everything to seconds (since that's the base unit of "time"). This prevents other operations getting confused by scaled units, which happens when you use "auto" because it skips this conversion.
Ah I gotcha. So the prevailing wisdom is auto auto auto, except when quantities and prefixed unit conversions are concerned. Thank you...
_______________________________________________ Boost-users mailing list Boost-users@lists.boost.org http://lists.boost.org/mailman/listinfo.cgi/boost-users
-- Sent from my Android device with K-9 Mail. Please excuse my brevity.

On 11/08/2015 14:12, Michael wrote:
You can, but it's not necessary. Simply assign value * milli * seconds
to a variable of quantity<time> (aka Time) and it automatically converts everything to seconds (since that's the base unit of "time"). This prevents other operations getting confused by scaled units, which happens when you use "auto" because it skips this conversion.
Ah I gotcha. So the prevailing wisdom is auto auto auto, except when quantities and prefixed unit conversions are concerned.
I'm not sure about "prevailing wisdom". I don't use auto anywhere with Boost.Units (I use explicit types as mentioned above instead). But then, most of my usage of Boost.Units was written in the dark ages (C++03 compiler). TBH your code seems a little too auto-happy to me -- I wouldn't have defined things like "two" or "milliseconds" or "gValue" or the static_casts and would have just written the values inline instead, as I think it's sufficiently clear that way. But that's just a coding style thing (the compiler should be smart enough to generate the same code either way) and if you think that makes it clearer for you then go for it. That's probably a more reasonable place to use "auto", for things that aren't quantities.

On Mon, Aug 10, 2015 at 10:50 PM, Gavin Lambert <gavinl@compacsort.com> wrote:
On 11/08/2015 14:12, Michael wrote:
You can, but it's not necessary. Simply assign value * milli * seconds
to a variable of quantity<time> (aka Time) and it automatically converts everything to seconds (since that's the base unit of "time"). This prevents other operations getting confused by scaled units, which happens when you use "auto" because it skips this conversion.
Ah I gotcha. So the prevailing wisdom is auto auto auto, except when quantities and prefixed unit conversions are concerned.
I'm not sure about "prevailing wisdom". I don't use auto anywhere with Boost.Units (I use explicit types as mentioned above instead). But then, most of my usage of Boost.Units was written in the dark ages (C++03 compiler).
TBH your code seems a little too auto-happy to me -- I wouldn't have defined things like "two" or "milliseconds" or "gValue" or the static_casts and would have just written the values inline instead, as I think it's sufficiently clear that way. But that's just a coding style thing (the compiler should be smart enough to generate the same code either way) and if you think that makes it clearer for you then go for it. That's probably a more reasonable place to use "auto", for things that aren't quantities.
No problem. Thanks for the critique anyhow. It's an early prototype, just pulling some concepts together. I'll likely rewrite it 2-3 times anyway, before it's all said and done. I'm already capturing "calculator" concerns such as "e" and "g" as true-quantity constants in a calculator structure, for example. I'm finding that helps add clarity to the code, as well. Still, I like auto when it makes sense; kind of like C# var.
_______________________________________________ Boost-users mailing list Boost-users@lists.boost.org http://lists.boost.org/mailman/listinfo.cgi/boost-users

On Mon, Aug 10, 2015 at 10:50 PM, Gavin Lambert <gavinl@compacsort.com> wrote:
On 11/08/2015 14:12, Michael wrote:
You can, but it's not necessary. Simply assign value * milli * seconds
to a variable of quantity<time> (aka Time) and it automatically converts everything to seconds (since that's the base unit of "time"). This prevents other operations getting confused by scaled units, which happens when you use "auto" because it skips this conversion.
Ah I gotcha. So the prevailing wisdom is auto auto auto, except when quantities and prefixed unit conversions are concerned.
I'm not sure about "prevailing wisdom". I don't use auto anywhere with Boost.Units (I use explicit types as mentioned above instead). But then, most of my usage of Boost.Units was written in the dark ages (C++03 compiler).
This does work. const quantity<time> value_(value * milli * seconds); Thank you...
TBH your code seems a little too auto-happy to me -- I wouldn't have defined things like "two" or "milliseconds" or "gValue" or the static_casts and would have just written the values inline instead, as I think it's sufficiently clear that way. But that's just a coding style thing (the compiler should be smart enough to generate the same code either way) and if you think that makes it clearer for you then go for it. That's probably a more reasonable place to use "auto", for things that aren't quantities.
_______________________________________________ Boost-users mailing list Boost-users@lists.boost.org http://lists.boost.org/mailman/listinfo.cgi/boost-users
participants (3)
-
Gavin Lambert
-
Michael
-
Michael Powell