Preliminary submission - std.rational and std.typelist
David Nadlinger
see at klickverbot.at
Sat Oct 6 14:18:23 PDT 2012
On Saturday, 6 October 2012 at 19:40:10 UTC, Arlen wrote:
> Besides, the math behind it is sound and and many years of hard
> work has gone into it.
Also, it is extremely complicated by the fact that it somehow has
to work withing the boundaries of C++ and boost::mpl and friends.
> I do want to mention that the distinction between dimension and
> unit is important.
Why? From a theorist standpoint, there of course is a distinction
between the two, yes. In practice, however, a dimension is simply
a connected component in the graph of (non-composite) units,
where the edges represent known conversions, i.e. a dimension is
just a name for a set of units which can converted into each
other. The concept of dimensions arises naturally, and no rigor
is lost by not explicitly having it; there is no need to force
the redundancy on the programmer.
In fact, my library was also based on dimensions originally, but
at some point, they became an annoyance in the code I wrote using
it, and I discovered that I could do perfectly fine without them.
> I rather see this:
>
> Quantity!(length, float) a = 2 * metre;
>
> than this:
>
> Quantity!(metre, float) a = 2 * metre;
Really? The first has the problem that you have absolutely no
idea what a is really represented like in memory – you need to
have a canonical base unit all other units are automatically
converted to. One consequence of that is that you are forced to
do a lot of unneeded conversions if you can't completely work in
that base unit, for example for interfacing with code that
doesn't use your unit system. You also can't just transparently
tack a unit on a quantity in places where the actual value is
important, think serialization, ABI boundaries, etc. Not being
able to chose your representation might also lead to precision
issues if you are working with base types of limited width.
In contrast, the concept of dimensions is easy to implement in
terms of units. For example, you could just define 'isLength' as
'canConvert!meter' (it will accept any unit which can somehow,
maybe not directly, converted into meters), and then implement a
function like this:
---
auto squareArea(T)(T side) if (isQuantity!T && isLength!(T.unit))
{
return side * side;
}
---
squareArea now works transparently and without overhead with all
unit types. Of course, you could also define the parameter as
just Quantity!(meter, T) or Quantity!(meter, float) if for some
reason you want to, for example because you are only working in
meters anyway and you don't want to have a template function to
avoid the (compile-time) overhead.
I think the main reason why Boost.Units went with dimensions is
that having a distinguished "canonical" unit for each dimension
relieves the burden on the implementation in so far as you never
have to synthesize code for arbitrary conversions, as your data
is always stored in that canonical unit.
David
More information about the Digitalmars-d
mailing list