Last active
September 11, 2016 01:10
Compiler-Enforced Semantic Types Sample Implementation (based on Bjarne Stroustrup's talk at https://youtu.be/0iWb_qi2-uI?t=19m6s)
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
//Compiled with clang -std=c++14 -Weverything -Wno-c++98-compat main.cpp -o main | |
#include <iostream> | |
#include <string> | |
template<int M, int K, int S> //Meters, Kilograms, Seconds (MKS) | |
struct Unit | |
{ | |
enum { m=M, kg=K, s=S }; | |
}; | |
template<typename Unit> //a magnitude with a unit | |
struct Value | |
{ | |
double val; //the magnitude | |
constexpr explicit Value(double d) : val(d) {} //construct a Value from a double | |
}; | |
//Basic Semantic Units for MKS domain | |
using Meter = Unit<1, 0, 0>; | |
using Kilogram = Unit<0, 1, 0>; | |
using Second = Unit<0, 0, 1>; | |
using Second2 = Unit<0, 0, 2>; | |
//Semantic Value Types for MKS domain | |
using Time = Value<Second>; | |
using Distance = Value<Meter>; | |
using Mass = Value<Kilogram>; | |
using Speed = Value<Unit<1, 0, -1>>; //Speed is meters/second | |
using Acceleration = Value<Unit<1, 0, -2>>; //Acceleration is meters/second^2 | |
//Operator overloads to properly calculate units (incomplete; for demo purposes) | |
Speed operator/(const Distance& lhs, const Time& rhs) | |
{ | |
return Speed(lhs.val / rhs.val); | |
} | |
Acceleration operator/(const Speed& lhs, const Time& rhs) | |
{ | |
return Acceleration(lhs.val / rhs.val); | |
} | |
//Define literals | |
constexpr Distance operator"" _m(long double ld) | |
{ | |
return Distance(static_cast<double>(ld)); | |
} | |
constexpr Mass operator"" _kg(long double ld) | |
{ | |
return Mass(static_cast<double>(ld)); | |
} | |
constexpr Time operator"" _s(long double ld) | |
{ | |
return Time(static_cast<double>(ld)); | |
} | |
constexpr Acceleration operator"" _s2(long double ld) | |
{ | |
return Acceleration(static_cast<double>(ld)); | |
} | |
int main() | |
{ | |
Speed sp = Distance(100)/Time(9.58); //Not bad, but units could be more convenient... | |
Distance d1 = 100.0_m; //A good distance to run a race | |
Speed sp1 = 100.0_m/9.58_s; //A human can run this fast | |
// Speed sp3 = 100.0/9.8_s; //Error: 100 has no unit | |
// Speed sp2 = 100.0_m/9.8_s2; //Error: speed is m/s, not m/s^2 | |
Acceleration ac1 = sp1/0.5_s; //Faster than any human | |
return EXIT_SUCCESS; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment