Boost logo

Boost :

From: Matthias Schabel (boost_at_[hidden])
Date: 2007-03-26 14:51:13


>> The problem with these non-standard units is that they don't really
>> form a
>> well-defined unit system. ...
>> We have, however, supplied a number of examples of how to
>> roll your own unit system...
>> )
>
> I agree with Zach and also want to be able to define units without
> having to "roll my own unit system".

There is no way to avoid having some tag class to differentiate units
having the same dimensional signature - it's just impossible to do it
and preserve the ability to do zero-runtime overhead calculations.
You don't have to define a system, but every unit needs to have a
unique dimensional signature and a tag. Consider definition of the
unit for gallon :

struct imperial : public ordinal<1000> { };

typedef unit<volume_type,imperial> imperial_gallon;

struct us : public ordinal<1001> { };

typedef unit<volume_type,us> us_gallon;

The ordinal is necessary to be able to sort dimension lists and
can't be gotten around because there's no way to have the
compiler generate a unique enumerated sequence of values.
It's hard to get much more concise than this... You can then define
conversions between the two :

/// convert imperial gallons to us gallons
template<class Y>
class conversion_helper< quantity<unit<volume_type,imperial>,Y>,
                          quantity<unit<volume_type,us>,Y> >
{
     public:
         typedef quantity<unit<volume_type,imperial>,Y>
from_quantity_type;
         typedef quantity<unit<volume_type,us>,Y>
to_quantity_type;

         static
         to_quantity_type
         convert(const from_quantity_type& source)
         {
             const typename from_quantity_type::value_type& in
(source.value());

             return to_quantity_type::from_value(in.value()
*1.2009499255);
         }
};

/// convert us gallons to imperial gallons
template<class Y>
class conversion_helper< quantity<unit<volume_type,us>,Y>,
                          quantity<unit<volume_type,imperial>,Y> >
{
     public:
         typedef quantity<unit<volume_type,us>,Y>
from_quantity_type;
         typedef quantity<unit<volume_type,imperial>,Y>
to_quantity_type;

         static
         to_quantity_type
         convert(const from_quantity_type& source)
         {
             const typename from_quantity_type::value_type& in
(source.value());

             return to_quantity_type::from_value(in.value()/
1.2009499255);
         }
};

That's all you need to do to define your own units. If you want them
to be implicitly
convertible, then you need to also define that :

template<>
struct is_implicitly_convertible<unit<volume_type,imperial>,
                                  unit<volume_type,us> > :
     public mpl_::true_
{ };

template<>
struct is_implicitly_convertible<unit<volume_type,us>,
                                  unit<volume_type,imperial> > :
     public mpl_::true_
{ };

Matthias


Boost list run by bdawes at acm.org, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk