You seriously don't understand why it's desirable to get a compiler error if someone has a quantity in centimeters and tries to use it where a quantity in inches is expected?

This is not my point. My point is thats not a compiler (c++ grammar) problem. Its worth implementing as a part of an STL.

Well, it's a problem where the compiler could help, if it implemented what we are discussing.

I have felt the need for something like this when I have classes Vector3D and Point3D, which are essentially the same thing, but I need to define them separately if I want the type system to help me make sure my operations make sense (e.g., you are not allowed to add points, but adding vectors is fine, and so is adding a point and a vector).

Since we are dealing with units, I just wrote this little test that seems to work fine:

#include <iostream>
namespace units {
template <int m_pow, int kg_pow, int s_pow>
struct unit {
double value;
explicit unit(double value) : value(value) {
}
};
template <int m_pow, int kg_pow, int s_pow>
unit<m_pow,kg_pow,s_pow> operator+(unit<m_pow,kg_pow,s_pow> u1, unit<m_pow,kg_pow,s_pow> u2) {
return unit<m_pow,kg_pow,s_pow>(u1.value+u2.value);
}
unit<0,0,0> operator+(unit<0,0,0> u, double d) {
return unit<0,0,0>(u.value+d);
}
unit<0,0,0> operator+(double d, unit<0,0,0> u) {
return unit<0,0,0>(d+u.value);
}
template <int m_pow, int kg_pow, int s_pow>
unit<m_pow,kg_pow,s_pow> operator-(unit<m_pow,kg_pow,s_pow> u1, unit<m_pow,kg_pow,s_pow> u2) {
return unit<m_pow,kg_pow,s_pow>(u1.value-u2.value);
}
unit<0,0,0> operator-(unit<0,0,0> u, double d) {
return unit<0,0,0>(u.value-d);
}
unit<0,0,0> operator-(double d, unit<0,0,0> u) {
return unit<0,0,0>(d-u.value);
}
template <int m_pow1, int kg_pow1, int s_pow1, int m_pow2, int kg_pow2, int s_pow2>
unit<m_pow1+m_pow2,kg_pow1+kg_pow2,s_pow1+s_pow2> operator*(unit<m_pow1,kg_pow1,s_pow1> u1, unit<m_pow2,kg_pow2,s_pow2> u2) {
return unit<m_pow1+m_pow2,kg_pow1+kg_pow2,s_pow1+s_pow2>(u1.value*u2.value);
}
template <int m_pow, int kg_pow, int s_pow>
unit<m_pow,kg_pow,s_pow> operator*(unit<m_pow,kg_pow,s_pow> u, double d) {
return unit<m_pow,kg_pow,s_pow>(u.value*d);
}
template <int m_pow, int kg_pow, int s_pow>
unit<m_pow,kg_pow,s_pow> operator*(double d, unit<m_pow,kg_pow,s_pow> u) {
return unit<m_pow,kg_pow,s_pow>(d*u.value);
}
template <int m_pow1, int kg_pow1, int s_pow1, int m_pow2, int kg_pow2, int s_pow2>
unit<m_pow1-m_pow2,kg_pow1-kg_pow2,s_pow1-s_pow2> operator/(unit<m_pow1,kg_pow1,s_pow1> u1, unit<m_pow2,kg_pow2,s_pow2> u2) {
return unit<m_pow1-m_pow2,kg_pow1-kg_pow2,s_pow1-s_pow2>(u1.value/u2.value);
}
template <int m_pow, int kg_pow, int s_pow>
unit<m_pow,kg_pow,s_pow> operator/(unit<m_pow,kg_pow,s_pow> u, double d) {
return unit<m_pow,kg_pow,s_pow>(u.value/d);
}
template <int m_pow, int kg_pow, int s_pow>
unit<m_pow,kg_pow,s_pow> operator/(double d, unit<m_pow,kg_pow,s_pow> u) {
return unit<-m_pow,-kg_pow,-s_pow>(d/u.value);
}
template <int m_pow, int kg_pow, int s_pow>
std::ostream &operator<<(std::ostream &os, unit<m_pow,kg_pow,s_pow> u) {
os << u.value;
if (m_pow != 0) {
os << "m";
if (m_pow != 1)
os << "^" << m_pow;
}
if (kg_pow != 0) {
os << "Kg";
if (kg_pow != 1)
os << "^" << kg_pow;
}
if (s_pow != 0) {
os << "s";
if (s_pow != 1)
os << "^" << s_pow;
}
return os;
}
unit<1,0,0> meter(1);
unit<1,0,0> centimeter(0.01);
unit<1,0,0> inch(0.0254);
unit<0,0,1> second(1.0);
unit<0,0,1> minute(60.0);
unit<0,0,1> hour(3600.0);
unit<0,1,0> gram(0.001);
// etc.
}
using namespace units;
int main() {
std::cout << "100 inches/hour = " << (100.0*inch/hour)/(centimeter/minute) << " centimeters/minute\n";
}

Does anyone know if there is a C++ library that does this type of thing? (Oh, and sorry about the hijack...)