I don't know whether Rust's current const
generics would make this nice, but you could try out something I'll call "compile-time homogeneous coordinates".
It'd be something like this:
struct Homogeneous<T, const W: isize>([T; 3]);
type Point<T> = Homogeneous<T, 1>;
type Vector<T> = Homogeneous<T, 0>;
Then you have
impl<T, const W1: usize, const W2: usize> Add<Homogeneous<T, W2>> for Homogeneous<T, W1> {
type Output = Homogeneous<T, W1 + W2>;
...
}
impl<T, const W1: usize, const W2: usize> Sub<Homogeneous<T, W2>> for Homogeneous<T, W1> {
type Output = Homogeneous<T, W1 - W2>;
...
}
That means you can do p1 + p2 - p3
and still get a Point
as it should be, without needing to p1 + (p2 - p3)
to fit the intermediate types into what you've defined. Similarly, it'd be fine to Neg
a point, it just would give you something distinct from both Point
s and Vector
s, but if you added another Point
to it you'd get back to a Vector
.
It also has the nice advantage that you don't need to write separate Sub
impls for Point-Point
, Point-Vector
, and Vector-Vector
, since they all just work and do the thing you wanted.
(I assume someone else has thought of this before, but I've not actually seen it.)