When working with generics, the type parameters (e.g. Ty) may use traits
(e.g. Tr) as bounds (e.g. Ty: Tr, which reads as: Ty must implement the
Tr trait). Bounding has two effects:
Generics instances (let ty: Ty = (...)) can now access the methods
(ty.tr()) of the traits specified in the bounds.
The generic can only be specialized for type parameters that conform to the
bounds.
#[deriving(Show)]
struct Vec2<T> {
x: T,
y: T,
}
impl<
// Bound: `T` must implement the `Add` trait
T: Add<T, T>
> Add<Vec2<T>, Vec2<T>>
for Vec2<T> {
fn add(&self, rhs: &Vec2<T>) -> Vec2<T> {
Vec2 {
// `x` and `y` are of type `T`, and implement the `add` method
x: self.x.add(&rhs.x),
// The sugary `+` operator can also be used
y: self.y + rhs.y,
}
}
}
impl<
// Bound: `T` must implement the `Sub` trait
T: Sub<T, T>
> Sub<Vec2<T>, Vec2<T>>
for Vec2<T> {
fn sub(&self, rhs: &Vec2<T>) -> Vec2<T> {
Vec2 {
x: self.x - rhs.x,
y: self.y - rhs.y,
}
}
}
impl<
// Bound: `T` must implement *both* the `Add` trait and the `Mul` trait
T: Add<T, T> + Mul<T, T>
> Mul<Vec2<T>, T>
for Vec2<T> {
fn mul(&self, rhs: &Vec2<T>) -> T {
(self.x * rhs.x) + (self.y * rhs.y)
}
}
fn main() {
// Floats implement the `Add`, `Mul` and `Sub` traits
let v1 = Vec2 { x: 1.2_f32, y: 3.4 };
let v2 = Vec2 { x: 5.6_f32, y: 7.8 };
println!("{} + {} = {}", v1, v2, v1 + v2);
println!("{} - {} = {}", v1, v2, v1 - v2);
println!("{} . {} = {}", v1, v2, v1.dot(&v2));
// Error! `char` doesn't implement the `Add` trait
println!("{}", Vec2 { x: ' ', y: 'b' } + Vec2 { x: 'c', y: 'd' });
// FIXME ^ Comment out this line
}