Let me see if I can dig up the code.
#include <type_traits>
#include <iostream>
#include <string>
template <typename dimensions> struct quantity
{
public:
float value;
quantity(float f = 0.0f)
: value(f)
{
}
float operator=(float f)
{
return value = f;
}
float operator=(quantity)
{
return value = f;
}
};
template <int mass, int distance, int time> class Dimensions {};
typedef Dimensions<1, 0, 0> Kilogram;
typedef Dimensions<0, 1, 0> Metre;
typedef Dimensions<0, 0, 1> Second;
template <int A, int B, int C> //, template <class, typename> typename T
std::ostream &operator <<(std::ostream &os, quantity<Dimensions<A, B, C>> q)
{
os << q.value;
if (A != 0)
{
os << "kg";
if (A != 1)
{
os << "^" << A;
}
}
if (B != 0)
{
os << "m";
if (B != 1)
{
os << "^" << B;
}
}
if (C != 0)
{
os << "s";
if (C != 1)
{
os << "^" << C;
}
}
return os;
}
template <int A, int B, int C>
quantity<Dimensions<A, B, C>> operator +(quantity < Dimensions<A, B, C>> a, quantity < Dimensions<A, B, C>> b)
{
quantity<Dimensions<A, B, C>> c;
c.value = a.value + b.value;
return c;
}
template <int d11, int d12, int d13, int d21, int d22, int d23>
quantity<Dimensions<d11 + d21, d12 + d22, d13 + d23>> operator *(quantity < Dimensions<d11, d12, d13>> a, quantity < Dimensions<d21, d22, d23>> b)
{
quantity<Dimensions<d11 + d21, d12 + d22, d13 + d23>> c;
c.value = a.value * b.value;
return c;
}
template <int d1, int d2, int d3>
void units(quantity < Dimensions<d1, d2, d3>>)
{
}
template <int d11, int d12, int d13, int d21, int d22, int d23>
quantity<Dimensions<d11 - d21, d12 - d22, d13 - d23>> operator /(quantity < Dimensions<d11, d12, d13>> a, quantity < Dimensions<d21, d22, d23>> b)
{
quantity<Dimensions<d11 - d21, d12 - d22, d13 - d23>> c;
c.value = a.value / b.value;
return c;
}
int main()
{
quantity<Metre> dist1 = 1.5f;
std::cout << "Length 1: " << dist1 << "\n";
quantity<Metre> dist2 = 2.0f;
std::cout << "Length 2: " << dist2 << "\n";
auto dist3 = dist1 + dist2;
std::cout << "Length 1 + Length 2: " << dist3 << "\n";
auto dist4 = dist1 * dist2;
std::cout << "Length 1 * Length 2: " << dist4 << "\n";
quantity<Second> time1 = 1.0f;
std::cout << "Time: " << time1 << "\n";
auto velocity = dist1 / time1;
std::cout << "Velocity: " << velocity << "\n";
std::cin.get();
return 0;
}
If anyone wants to play with what I got working, that should be it. But I haven't run that code in a while, YMMV. Note that when storing the result of a computation, you can use auto as the return type, if you just want to store it, or you can typedef specific dimensions and give them a name, these are the ones already defined as an example:
typedef Dimensions<1, 0, 0> Kilogram;
typedef Dimensions<0, 1, 0> Metre;
typedef Dimensions<0, 0, 1> Second;
but you could make ones like these :
typedef Dimensions<0, 1, -1> Velocity;
typedef Dimensions<0, 1, -2> Acceleration;
To use these you make a "quantity<Velocity>" variable for example, but alternatively you could typedef the container type itself : typedef quantity<Dimensions<0, 1, -1>> Velocity;
So, what the goal would be is that all physics units that can be defined in the kms system can be typedef'd in this system, then hopefully, only physically meaningful computations would be allowed.
So, many SI units could be defined computationally with the code given:
https://en.wikipedia.org/wiki/SI_derived_unitHmm, I just realized if I add A, Amperes as a fourth dimension then I can add in a ton of the other SI units.