Mixin template containing the implementation of the unit instance operators.

Furthermore, it marks the surrounding type as unit – every unit type has to mixin this template.

In addition, a unit type might also define a toString() function returning a custom unit symbol/name, and a list of Conversions. The example shows how a unit type for inches might be defined if scale and ScaledUnit did not exist (which remove the need to write boilerplate code like this).



auto opBinary(Rhs rhs)
auto opBinary(Rhs rhs)

Multiplication/division of two unit instances, yielding a unit instance representing the product/quotient unit.

auto opBinary(V rhs)
auto opBinary(V rhs)
auto opBinaryRight(V lhs)
auto opBinaryRight(V lhs)

Multiplication/division of an unit and a value type, constructing a Quantity instance.


1 struct Inch {
2    mixin UnitImpl;
4    static string toString(UnitString type = UnitString.name) {
5        final switch (type) {
6            case UnitString.name: return "inch";
7            case UnitString.symbol: return "in";
8        }
9    }
11    alias AliasSeq!(
12        Conversion!(centi(metre), toCm, fromCm)
13    ) Conversions;
15    static V toCm(V)(V v) {
16        return cast(V)(v * 2.54);
17    }
18    static V fromCm(V)(V v) {
19        return cast(V)(v / 2.54);
20    }
21 }
22 enum inch = Inch.init; // Unit instance to use with abbreviated syntax.

Note: Two existing units a and c can't be retroactively extended with a direct conversion between them. This is by design, as it would break D's modularization/encapsulation approach (alternative: use mixin template for defining conversion functions, then it would be possible to have different behavior of the conversion function in each module). However, currently it is possible to create a third unit b which is convertible to both a and c, and then perform the conversion in two steps: convert!c(convert!b(1 * a))