Did you know that you can navigate the posts by swiping left and right?

C++ Units

01 Mar 2016 . Cpp . Comments #cpp #math

What if we could write math in code as we write it in the whiteboard ?
For instance, write the human body terminal velocity as T=200km/h and make the compiler understand it as a Velocity type, and check accordingly.
Well, let’s first define a Meter with a convenient print function:

class Meter {
public:
    long double d;
    constexpr Meter(long double d) : d(d) { }
    friend std::ostream& operator<< (std::ostream& out, const Meter& m) {
        out << std::fixed << m.d << "m";
    }
};

Now let’s define a Second alike:

class Second {
public:
    long double d;
    constexpr Second(long double d) : d(d) { }
    friend std::ostream& operator<< (std::ostream& out, const Second& s) {
        out << std::fixed << s.d << "s";
    }
};

And the Velocity, of course:

class Velocity {
public:
    long double d;
    constexpr Velocity(long double d) : d(d) { }
    friend std::ostream& operator<< (std::ostream& out, const Velocity& v) {
        out << std::fixed << v.d << "m/s";
    }
};

Now we need the compiler to recognize the “/” symbol between a Meter and a Second
and generate a Velocity type:
(remember the operator must be in global scope)

Velocity operator/ (const Meter& m, const Second& s) {
    return Velocity(m.d/s.d);
}

One more step is to instruct the compiler to recognize the “km” postfix.
However the “k” is a modifier and the real type is “m”.
Once again in global scope, let’s define the operators for “m” and “s”:
(the underscore is there only to avoid clashes)

constexpr Meter operator"" _m (long double d) {
    return Meter(d);
}
constexpr Second operator"" _s (long double d) {
    return Second(d);
}

Finaly we can work the magic:

int main(int argc, char** argv) {
    std::cout << 200000._m/3600._s << std::endl;
    return 0;
}

And the console will show:

55.555556m/s

glhf