Trying to determine the Add character for custom types, you do this:
impl<T: HasValue + Copy, O: HasValue + Copy> Add<O, AddOp<T, O>> for T { fn add(&self, other : &O) -> AddOp<T, O> { AddOp { lhs: *self, rhs: *other } } }
But T: HasValue + Copy matches any sign of an implementation of type HasValue , and this type cannot be defined in your box (for example, if you implement HasValue for int ). Since Add not defined in your box, Rust complains: for example, by defining HasValue for int , you also override Add for int !
My suggestion was to wrap all your operations and structs values ββin common, and implement Add and Mul for it. Thus, you implement Add and Mul only for the simple type defined in your box, and the compiler is happy.
Something like that:
struct Calculus<T: HasValue + Copy> { calc: T } impl<T: HasValue + Copy> HasValue for Calculus<T> { fn get_value(&self) -> int { self.calc.get_value() } } impl<T, O> Add<Calculus<O>, Calculus<AddOp<T, O>>> for Calculus<T> where T: HasValue + Copy, O: HasValue + Copy { fn add(&self, other : &Calculus<O>) -> Calculus<AddOp<T, O>> { Calculus { calc: AddOp { lhs: self.calc, rhs: other.calc } } } } impl<T, O> Mul<Calculus<O>, Calculus<MulOp<T, O>>> for Calculus<T> where T: HasValue + Copy, O: HasValue + Copy { fn mul(&self, other : &Calculus<O>) -> Calculus<MulOp<T, O>> { Calculus { calc: MulOp { lhs: self.calc, rhs: other.calc } } } }
Then you can simply add the neat new() method for your Val type:
impl Val { fn new(n: int) -> Calculus<Val> { Calculus { calc: Val { value: n } } } }
and use it all like this:
fn main() { let a = Val::new(1); let b = Val::new(2); let c = Val::new(3); let e = ((a + b) * c).get_value(); print!("{}", e); }