Boost logo

Boost :

From: Deane_Yang_at_[hidden]
Date: 2001-09-15 13:11:43


This looks good to me. It's exactly what I have but without using
the boost classes (which makes it a lot easier and cleaner). Add
something like

template <class NewUnitType, class OldUnitType>
NewUnitType
  unit_cast<NewUnitType,OldUnitType>(OldUnitType quantity);

plus classes defining derived units (ratios, powers, products),
and you've pretty much got it all. Use template specialization to
implement only the conversions that you want.

Then to define a framework for something like SIUnits, you just
define a dimension class very similar to the unit class below that
contains among other things
a template constructor like

template <class UnitType>
dimension::dimension(UnitType quantity)
:value_(unit_cast<default_unit_type, UnitType>(quantity))
{}

and a casting operator like:

// Does this work?
template <class UnitType>
operator UnitType()
{
  return unit_cast<UnitType, default_unit_type>(value_);
}

Now using template specialization for unit_cast, you can control
which units are associated with a given dimension.

Also, you need the ratio, powers, and products for the dimension
classes.

It would appear that you only need to define the dimension class
and let the unit class be dimension<double>.

I haven't examined the guts of SIUnits, but if this is how SIUnits
is implemented, then it's exactly what I want.

Deane

--- In boost_at_y..., eford_at_m... wrote:
> > construct each object, but for other software you would want
to
> > associate specific units to the objects and to have
> >
> > time_in_seconds = distance_in_cm / velocity_in_mph
> >
> > to give a compiler error. Most of my work falls in the latter
> > category. That's why I'm asking for the more basic library
> > that does not have automatic conversions between units that
> > measure the same quantity.
>
> How would this differ from?
>
> template<class T, int ID>
> class unit_unconvertible :
> boost::totally_ordered<unit_unconvertible<T,ID> >,
> boost::integer_arithmetic<unit_unconvertible<T,ID> >,
> boost::unit_steppable<unit_unconvertible<T,ID> >
> {
> public:
> typedef unit_unconvertible<T,ID> unit_unconvertible_type;
> typedef unit_unconvertible_type self_type;
> typedef self_type& self_reference;
> typedef const self_reference self_const_reference;
> typedef self_const_reference self_param_type;
> typedef typename boost::call_traits<T>::value_type
value_type;
> typedef typename boost::call_traits<T>::reference reference;
> typedef typename boost::call_traits<T>::param_type
param_type;
> typedef int id_type;
> protected:
> static const id_type mId = ID;
> value_type mVar;
> reference get() { return mVar; };
> public:
> unit_unconvertible(param_type x) : mVar(x) {};
> param_type get() const { return mVar; };
>
> bool operator<(self_param_type x) const { return (get()<
x.get());
> };
> bool operator==(self_param_type x) const { return
> (get()==x.get()); };
> self_reference operator+=(self_param_type x) { get()+=
x.get();
> return *this; };
> self_reference operator-=(self_param_type x) { get()-=
x.get();
> return *this; };
> self_reference operator*=(self_param_type x) { get()*=
x.get();
> return *this; };
> self_reference operator/=(self_param_type x) { get()/=x.get();
> return *this; };
> self_reference operator%=(self_param_type x) { get()%=
x.get();
> return *this; };
> self_reference operator++() { get()++; return *this; };
> self_reference operator--() { get()--; return *this; };
>
> };
>
>
> template<class T, int ID>
> ostream& operator<<( ostream& os, const
unit_unconvertible<T,ID>& x)
> { return (os << x.get()); };
>
>
> int main(int argc, char** argv)
> {
> unit_unconvertible<float,1> x = 1.;
> unit_unconvertible<float,1> y = 2.;
> cout << "x = " << x << " y = " << y << endl;
> x+=y;
> y*=x;
> cout << "x = " << x << " y = " << y << endl;
> return 0;
> }


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