Wouldn't it be nice if this would be possible?
int main() { Second a(2); Second b(4); Second c = a + b; c += b; Meter d(3); std::cout << d.toString() << "\n"; std::cout << c.toString() << "\n"; Velocity v = d/a; std::cout << v.toString() << "\n"; }
Where the output would be:
3 m^1 10 s^1 1.5 s^-1 m^1
Below you can find the implementation of a compile time type safe SI system in C++ using templates :) The only thing I'm not happy with: the error messages are somewhat unreadable ;-)
#include <sstream> #include <iostream> template < int SECOND = 0, int METER = 0, int KILOGRAM = 0, int AMPERE = 0, int KELVIN = 0, int MOL = 0, int CANDELA = 0> class Unit { template<int, int, int, int, int, int, int> friend class Unit; public: static const int s = SECOND; static const int m = METER; static const int kg = KILOGRAM; static const int A = AMPERE; static const int K = KELVIN; static const int mol = MOL; static const int cd = CANDELA; Unit() : value(0) {} explicit Unit(double v) : value(v) {} ~Unit() {} // default copy and assignment c'tor are ok // overload operators // "+" and "-" are easy Unit operator +(const Unit& other) { return Unit(value + other.value); } Unit operator -(const Unit& other) { return Unit(value - other.value); } void operator +=(const Unit& other) { value += other.value; } void operator -=(const Unit& other) { value -= other.value; } // "*" and "/" are more interesting ... but easy as well template <typename T> Unit< s+T::s, m+T::m, kg+T::kg, A+T::A, K+T::K, mol+T::mol, cd+T::cd> operator *(const T& other) { return Unit< s+T::s, m+T::m, kg+T::kg, A+T::A, K+T::K, mol+T::mol, cd+T::cd>(value*other.value); } template <typename T> Unit< s-T::s, m-T::m, kg-T::kg, A-T::A, K-T::K, mol-T::mol, cd-T::cd> operator /(const T& other) { return Unit< s-T::s, m-T::m, kg-T::kg, A-T::A, K-T::K, mol-T::mol, cd-T::cd>(value/other.value); } // *= and /= are not defined! double toDouble() const { return value; } std::string toString() const { std::stringstream ss; ss << value << " "; if (0 != s) { ss << "s^" << s << " "; } if (0 != m) { ss << "m^" << m << " "; } if (0 != kg) { ss << "kg^" << kg << " "; } if (0 != A) { ss << "A^" << A << " "; } if (0 != K) { ss << "K^" << K << " "; } if (0 != mol) { ss << "mol^" << mol << " "; } if (0 != cd) { ss << "cd^" << cd << " "; } return ss.str(); } private: // keeps the value double value; }; typedef Unit<1> Second; typedef Unit<0, 1> Meter; typedef Unit<-1> Hz; typedef Unit<-1, 1> Velocity; typedef Unit<-3, 2, 1> Watt; // I think you get the thingy ... int main() { Second a(2); Second b(4); Second c = a + b; c += b; Meter d(3); std::cout << d.toString() << "\n"; std::cout << c.toString() << "\n"; Velocity v = d/a; std::cout << v.toString() << "\n"; }