Boost logo

Boost :

From: Terje Slettebø (tslettebo_at_[hidden])
Date: 2003-04-30 14:05:54


>From: <renej_at_[hidden]>

> >> > Even if angle is added as a dimension, to an implementation using an
> >> > integer vector, it still wouldn't accommodate any other dimensions
> >> > added later, without rewriting the library and unit definitions.
> >>
> >> how about having the basic SI dimensions and a couple of extra
> >> "to-be-defined-by-the-developer" dimensions. In that case, full
> >> SI "compliance" and for those who want something extra they can have
> >> it. I saw one of the discussed unit libraries provided something like
> >> a dimension to be defined by the user/developer.
> >
> > I think I know a way this may be done, now: Default parameters.
> >
> > There's several ways of specifying a unit; one is to use a typelist,
> > such as "typedef mpl::vector_c<1,0,0,0,0,0,0> kg" (Dave Abrahams also
> > showed this approach at the recent ACCU conference), or use template
> > parameters for the dimensions. In both ways, defaults may be used (it's
> > used internally for mpl::vector, anyway). In fact, all could be
> > defaulted (like mpl::vector<>), giving in this case a dimensionless
> > unit.
> >
> > Named template parameters could be a possibility, as well, so you could
> > do "typedef unit<kg<>, m<>, s<-2> > newton".
>
> that would be nice; don't forget however that the value type should
> probably a template parameter also...

Yes, of course. :) The above was a simplified example. Actually, the one I'm
currently working on looks like this:

template<class Value, class Unit, class Prefix>
class dim;

It may be used like this (the first two mean the same):

typedef dim<double, unit<0,1,0,0,0,0,0>, prefix<3> > km;

typedef dim<double, si::unit::m, si::prefix::k> km;

si::m<double> length;
si::meter<double> length;
si::length<double> length;

The three latter ones mean the same thing - they declare dim-variables named
"length", of type meter (using inheritance from dim<> to simulate template
typedef). One might also default the value type to "double", so "si::m<>",
etc. may be used.

"dim" is short for "dimensional", to emphasize that it's not necessarily
just SI units. "quantity" is another possibility.

What's new here - and which I had in my earlier version, as well, is the
possibility to specify prefix, as well. This makes even more of a case for
having "unit" as a parameter in the dim/quantity template, rather than using
the exponent parameters there directly.

With this, you may use appropriate prefixes, e.g. "k", for "km", above, etc.
The value stored is still stored the same way, though; the prefix only
matters for initialisation, and reading the value for output.

Another thing I've been experimenting with, is to encode conversion factors,
including offset adjustment, so that you may convert between e.g. kelvin,
celcius and fahrenheit:

si::kelvin<double> k(283.15);
si::celcius<double> c;

c=k;

std::cout << c; // This will now print 10 degrees celcius (in whatever
formatting is used) (283.15 K)

All of this is done using static information encoded in the type. There's no
run-time overhead in computations, compared to built-in types.

If it's preferred, one may also disallow direct initialisation with values,
which is done above, and require explicit units for the value:

si::kelvin<double> k=283.15 * K;

This may incur some overhead, though, as it creates a dim temporary, and
uses copy initialisation of "k". In the earlier example, direct
initialisation is used.

> template <typename T> struct length : unit_type<T, ...> {}
> where unit_type<T, ...> has a "typedef unit<...> type;" in it
> so I can do: "length<float>::type my_len"

Well, I've just simulated template typedefs in another way, using
inheritance, as mentioned. That avoids the need to use "::type":

template<class T>
class length : public dim<T, si::m, si::prefix::unit>
{
  // Forwarding constructors here
};

Regards,

Terje


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