Operator overloading for all attribute structures in Rust

I am trying to implement C ++ style expression patterns in Rust using traits and operator overloading. I am stuck trying to overload the "+" and "*" for each structure of the expression template. The compiler complains about the implementation of the Add and Mul signs:

error: cannot provide an extension implementation where both attributes and type are not defined in this box

This error makes sense if type I trying to implement the attribute was constructive without my box, but the type is generic, which should implement the HasValue attribute that I defined.

Here is the code:

 trait HasValue { fn get_value(&self) -> int; } // Val struct Val { value: int } impl HasValue for Val { fn get_value(&self) -> int { self.value } } // Add struct AddOp<T1: HasValue + Copy, T2: HasValue + Copy> { lhs: T1, rhs: T2 } impl<T1: HasValue + Copy, T2: HasValue + Copy> HasValue for AddOp<T1, T2> { fn get_value(&self) -> int { self.lhs.get_value() + self.rhs.get_value() } } 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 } } } // Mul struct MulOp<T1: HasValue + Copy, T2: HasValue + Copy> { lhs: T1, rhs: T2 } impl<T1: HasValue + Copy, T2: HasValue + Copy> HasValue for MulOp<T1, T2> { fn get_value(&self) -> int { self.lhs.get_value() * self.rhs.get_value() } } impl<T: HasValue + Copy, O: HasValue + Copy> Mul<O, MulOp<T, O>> for T { fn mul(&self, other : &O) -> MulOp<T, O> { MulOp { lhs: *self, rhs: *other } } } fn main() { let a = Val { value: 1 }; let b = Val { value: 2 }; let c = Val { value: 2 }; let e = ((a + b) * c).get_value(); print!("{}", e); } 

Thoughts?

+6
source share
1 answer

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); } 
+2
source

Source: https://habr.com/ru/post/977105/


All Articles