I understand the confusion.
TKilometers is the quantity whereas TKilometer is the unit.
The names TLength, TMass were in the beginning to show that they are the reference unit, with factor 1, instead of Kilometer having a factor of 1000.
Though as it becomes almost transparent with automatic conversions, it would make sense to replace TLength by TMeters, TMass by TGrams etc. This is all fine until we get to more complicated units like TAcceleration, that would be TMetersPerSecond2 or TMetersPerSecondSquared. And there are much more complicated units.
I thought as well about separating the multiplier. It is possible, though it may require to add some brackets that may not be intuitive. Also it would be a bit longer. For example, "m" cannot be used for the factor milli because it is already taken by the meter.
d := 6*(milli*m); // this gives mm unit
Note that I prefer not multiply by the factor until it is necessary, to avoid loss of precision. So kilo*g would actually build factored unit, not exactly the same as 1000*g.
As I continue to experiment, it becomes clear that to reduce the number of operator definitions, I would need either:
- generic operators: similar to generic functions, but with operator, that could be applied to the various types that match the specializations.
- inheritance of class operators that refer to "self" type
The second one seems far fetched, it would require record inheritance and reinterpretation of signatures and implementing the "self" type.
So probably the most plausible would be the first one: generic operators. I don't know if this is something considered on trunk.