Boost logo

Boost Users :

Subject: [Boost-users] Boost.Units: Issue with user-defined and unitless quantities
From: Pieter (PieterB_at_[hidden])
Date: 2012-02-22 18:02:42


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+

 

 

 



Boost-users list run by williamkempf at hotmail.com, kalb at libertysoft.com, bjorn.karlsson at readsoft.com, gregod at cs.rpi.edu, wekempf at cox.net