LS,
This is a repost of an earlier question that unfortunately remained unanswered – I still hope sincerely someone out there can help me out as I feel really stuck here.
I have some problems working with user defined quantities/units in combination with unitless quantities (such as the results of a sin() or cos() operations).Taking the example of the ‘nautical mile’, which is presented in the documentation:
---START CODE ---
namespace nautical {
struct length_base_unit :
boost::units::base_unit<length_base_unit, length_dimension, 1>
{
static std::string name() { return "nautical mile"; }
static std::string symbol() { return "nmi"; }
};
typedef boost::units::make_system<length_base_unit>::type system;
typedef unit<length_dimension,system> length;
static const length mile,miles;
}
BOOST_UNITS_DEFINE_CONVERSION_FACTOR(nautical::length_base_unit,
boost::units::si::meter_base_unit,
double, 1.852e3);
---END CODE ---
The following does not compile:
---START CODE ---
typedef quantity<boost::units::si::plane_angle> TAngleInRad;
typedef boost::units::quantity<nautical::length> TNauticalDistanceInNMI;
TNauticalDistanceInNMI NauticalDistanceInNMI;
TNauticalDistanceInNMI SumNauticalDistanceInNMI = NauticalDistanceInNMI + NauticalDistanceInNMI; // OK
TNauticalDistanceInNMI ScaledSumNauticalDistanceInNMI = NauticalDistanceInNMI + NauticalDistanceInNMI*sin(AngleInRad);
// Last line does not compile due to lack of a suitable operator+
---END CODE ---
It does work correctly when using the ‘nautical mile’ as it has been defined in the library itself in “nautical_mile.hpp” (as a scaled base unit related to the si::meter):
---START CODE ---
namespace metric {
typedef scaled_base_unit<boost::units::si::meter_base_unit, scale<1852, static_rational<1> > > nautical_mile_base_unit;
} // definition of the nautical mile from “nautical_mile.hpp”
typedef boost::units::metric::nautical_mile_base_unit::unit_type nautical_mile_unit;
typedef quantity<nautical_mile_unit> TNauticalDistanceInNMI;
---END CODE ---
However, I don’t think I can specify my user-defined units/quantities in this manner as they use a scale factor represented by an arbitrary floating point value.
My perception is that the example of the documentation does not work due to the mixing of quantities from the si system (the sin() returns a dimensionless quantity in that system) with user-defined quantities in another (‘nautical’) system, while the ‘nautical mile’ from ‘nautical_mile.hpp’ is a scaled version of the si::meter and thus defined within the realms of the si::system – but please correct me if I am wrong here.
My problem can thus be summarized as follows:
- the solution from the documentation does not compile
- the solution from ‘nautical_mile.hpp’ uses a scaled base unit which is limited to scaling factors of the form scale<Base,Exponent>
and my question is therefore: how can I define my user-defined units/quantities in such a way that they allow the required operations while being related to base units by an arbitrary scale factor?
Help would be highly appreciated,
Pieter
-------------------
Nautical mile version #1 (from the included nautical_mile.hpp):
namespace metric {
typedef scaled_base_unit<boost::units::si::meter_base_unit, scale<1852, static_rational<1> > > nautical_mile_base_unit;
}
template<>
struct base_unit_info<metric::nautical_mile_base_unit>
{
static const char* name() { return("nautical mile"); }
static const char* symbol() { return("nmi"); }
};
typedef quantity<boost::units::si::plane_angle> TAngleInRad;
typedef quantity<boost::units::si::length> TDistanceInM;
typedef boost::units::metric::nautical_mile_base_unit::unit_type nautical_mile_unit;
typedef quantity<nautical_mile_unit> TDistanceInNMI;
typedef boost::units::quantity<nautical::length> TNauticalDistanceInNMI;
# this is OK:
TAngleInRad Angle(0.5*radians);
TDistanceInNMI DistanceInNMI;
TDistanceInNMI SumDistanceInNMI = DistanceInNMI + DistanceInNMI;
TDistanceInNMI ScaledSumDistanceInNMI = DistanceInNMI + DistanceInNMI*sin(AngleInRad);
TNauticalDistanceInNMI NauticalDistanceInNMI;
TNauticalDistanceInNMI SumNauticalDistanceInNMI = NauticalDistanceInNMI + NauticalDistanceInNMI;
TNauticalDistanceInNMI ScaledSum NauticalDistanceInNMI = NauticalDistanceInNMI + NauticalDistanceInNMI*sin(AngleInRad); // DOES NOT COMPILE for lack of a suitable operator+