Boost::Units - mapping from units object to something else
I'm looking at the Boost::Units classes to help eliminate a family of programming errors, but there is one thing that I'm having difficulty with: I have a collection of objects of my own type that pertains to units - these are of a fixed type, with instances per type of unit. I'd like to somehow be able to map from the units constants that Boost uses (e.g. boost:units:si:watts) into my objects (return the correct instance for "watts"). Obviously, there's going to be some hand coding to make that happen - it is unlikely to be possible to generate that mapping automatically. Ideally, what I'd like to do would be to have something like template <typename Unit> struct MyMapper { static const MyUnitInfo info; }; template <> const MyUnitInfoboost::units::si::watts::info(/*ctor parms for my type */); and do things like: MyMapperboost::units::si::watts::info to get the appropriate structure. However, since all the various Boost units are in a type hierarchy to express dimensionality, I'm at a loss how to compose a template to allow something like that to happen - it certainly isn't as straightforward as the above, since Boost units instances of varying types, not typenames. Likewise, just defining some form of map: std::map??,MyUnitInfo> mymap = boost::assign::map_list_of (boost::units::si::watts,MyUnitInfo(/* my parms*/)) (boost::units::si::ohms,MyUnitInfo(...)); won't work as the types for the Boost constants are all different as far as I can see. Is there some base type all the Boost::Units constants extend, such that I could test for that?
AMDG On 09/20/2013 10:34 AM, david.hagood@gmail.com wrote:
I'm looking at the Boost::Units classes to help eliminate a family of programming errors, but there is one thing that I'm having difficulty with:
I have a collection of objects of my own type that pertains to units - these are of a fixed type, with instances per type of unit.
I'd like to somehow be able to map from the units constants that Boost uses (e.g. boost:units:si:watts) into my objects (return the correct instance for "watts"). Obviously, there's going to be some hand coding to make that happen - it is unlikely to be possible to generate that mapping automatically.
Ideally, what I'd like to do would be to have something like
template <typename Unit> struct MyMapper { static const MyUnitInfo info; };
template <> const MyUnitInfoboost::units::si::watts::info(/*ctor parms for my type */);
and do things like:
MyMapperboost::units::si::watts::info
to get the appropriate structure.
However, since all the various Boost units are in a type hierarchy to express dimensionality, I'm at a loss how to compose a template to allow something like that to happen - it certainly isn't as straightforward as the above, since Boost units instances of varying types, not typenames.
I don't quite understand why this doesn't work. (Other than the obvious typos.) I also have no idea what you mean by "varying types, not typenames"
Likewise, just defining some form of map:
std::map??,MyUnitInfo> mymap = boost::assign::map_list_of (boost::units::si::watts,MyUnitInfo(/* my parms*/)) (boost::units::si::ohms,MyUnitInfo(...));
won't work as the types for the Boost constants are all different as far as I can see.
fusion::map can handle this.
Is there some base type all the Boost::Units constants extend, such that I could test for that?
No. If you want to identify units and quantities use the metafunctions is_unit and is_quantity. In Christ, Steven Watanabe
On 09/20/2013 11:11 PM, Steven Watanabe wrote:
(Other than the obvious typos.) I also have no idea what you mean by "varying types, not typenames"
Example:
boost::units::si::meter is a constant of type
unit
AMDG On 09/21/2013 05:18 AM, David Hagood wrote:
On 09/20/2013 11:11 PM, Steven Watanabe wrote:
(Other than the obvious typos.) I also have no idea what you mean by "varying types, not typenames"
Example: boost::units::si::meter is a constant of type unit
. boost::units:si::watts is a constant of type unit
. Since they are constants, any template would have to be of the form
template
struct mapper { static const MyStruct value; }; However, since unit_t is variant - unit
, unit , etc. - it has to be a template parameter as well - and come before the constant. So now the template would have to be:
template < typename dim_t, typename sys_t, const boost::units::unit
&units> struct mapper { static const MyStruct value; }; But now those paramters have to be specified in the use.
You don't have to make it that complex:
template<class T>
struct mapper;
template<>
sruct mapperboost::units::si::power
{
static const MyStruct value;
};
...
Usage:
mapper
The other approach would be to use a function: template < typename dim_t, typename sys_t> const MyStruct &Map(unit
const &value); which isn't bad on invocation: const MyStruct &x = Map(meters);
but gets more difficult on definition
template <> const MyStruct &Map
(unit const &) { static const MyStruct mymeters(/* parameters */); return mymeters; } template <> const MyStruct &Map
(unit const &) { static const MyStruct mywatts(/* parameters */); return mywatts; } since for every type you have to go look up the full dimensionality.
Don't specialize. Overload.
const MyStruct& Map(si::length);
const MyStruct& Map(si::mass);
const MyStruct& Map(si::power);
...
N.B. si::length = unit
Now, were there some base type for boost::units::unit
class unit_base { };
template
class unit: public unit_base { } Then this whole thing would be simpler, as they my code could use the base type to key off. (I would have to handle the fact there are multiple definitions in the library, e.g. meter/meters/metre/metres).
You shouldn't rely on the object identity. If you really wanted to do that, you could use void* as the key, anyway. In Christ, Steven Watanabe
participants (3)
-
David Hagood
-
david.hagood@gmail.com
-
Steven Watanabe