Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Literal with number and unit in an algebraic expression as argument

Tags:

c++

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

like image 440
tobilocker Avatar asked Jul 11 '18 12:07

tobilocker


2 Answers

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))
like image 184
NathanOliver Avatar answered Sep 30 '22 14:09

NathanOliver


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.

like image 29
Useless Avatar answered Sep 30 '22 14:09

Useless