How to design a type that can take an expression in the form of an algebraic expression with numbers and units, where Speed
is the type, 23m / 10s
could be an expression?
Example:
change_speed(Speed s); // better: the meaning of s is specified
// ...
change_speed(2.3); // error: no unit
change_speed(23m / 10s); // meters per second
EDIT This question raised the question if a literal in the form of 23m
is possible at all.
EDIT the reference to the source has been removed from question for clarity. It can be found here
What you have to do is design types that when the expression is evaluated it yields the desired type. With
change_speed(23m / 10s);
We need 23m
and 10s
to each yield a type that when you divide them together gives you a Speed
. If we have a
struct Meter
{
Meter(double value) : value(value) {}
double value;
};
struct Second
{
Second(double value) : value(value) {}
double value;
}
Speeds operator /(const Meter& m, const Second& s)
{
return Speed(m.value / s.value);
}
Then we just need to define literal operators for Meter
and Second
like
Meter operator "" _m(double value) { return Meter(value); }
Second operator "" _s(double value) { return Second(value); }
we have to use _m
and _s
to make these valid user defined literals. All literals besides those provided by the standard must start with a _
.
Then
change_speed(23_m / 10_s)
becomes
change_speed(Meter(23) / Second(10))
which becomes
change_speed(Speed(2.3))
It sounds like you want something like a units/dimensional analysis type system. See for example Boost.Units.
The fundamental (length, time, etc.) units are defined similarly to the duration types in std::chrono
- just with more than one (time) distinct dimension. The arithmetic operators are implemented to combine units into correctly-dimensioned compound types.
So, rather than defining Speed
as an independent type, it's derived from the fundamental Metre
and Second
types (which are themselves instances of the length and time units, which are probably instances of a generic unit template differentiated by tag types).
If you want to write user-defined literals for SI units, there are examples on codeproject or in this project on Github - I haven't read through either and can't vouch for their quality, but the idea is fine.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With