Providing implementation of blanket properties for a custom purpose

I am introducing a box with fast geometry for practice, and I want to implement two Vector and Normal structures (this is due to the fact that standard vectors and normal vectors display differently through certain transformations). I implemented the following symptom:

 trait Components { fn new(x: f32, y: f32, z: f32) -> Self; fn x(&self) -> f32; fn y(&self) -> f32; fn z(&self) -> f32; } 

I would also like to add two vectors together, as well as two normals, so I have blocks that look like this:

 impl Add<Vector> for Vector { type Output = Vector; fn add(self, rhs: Vector) -> Vector { Vector { vals: [ self.x() + rhs.x(), self.y() + rhs.y(), self.z() + rhs.z()] } } } 

And almost the same impl for Normal s. I really want to provide a default Add impl for each structure that implements Components , since they will usually all add the same path (for example, a third structure called Point will do the same). Is there a way to do this, besides writing three identical implementations for Point , Vector and Normal ? Something that might look like this:

 impl Add<Components> for Components { type Output = Components; fn add(self, rhs: Components) -> Components { Components::new( self.x() + rhs.x(), self.y() + rhs.y(), self.z() + rhs.z()) } } 

Where " Components " is automatically replaced by the corresponding type. I suppose I could do it in a macro, but it seems a bit hacked to me.

+3
source share
2 answers

Rust can define generic impl s, but there are some important limitations that impl from consistency rules. You want impl look like this:

 impl<T: Components> Add<T> for T { type Output = T; fn add(self, rhs: T) -> T { T::new( self.x() + rhs.x(), self.y() + rhs.y(), self.z() + rhs.z()) } } 

Unfortunately, this does not compile:

error: a type parameter T should be used as a type parameter for some local type (for example, MyStruct<T> ); only traits defined in the current box can be implemented for a parameter of type [ E0210 ]

Why? Suppose your Components trait was public. Now the type in another box can implement the Components trait. This type may also try to implement the Add attribute. Whose implementation of Add should win, your box or another box? By Rust's consistent consistency rules, another box gets this privilege.

Currently, the only option besides repeating impl s is to use a macro. The Rust standard library uses macros in many places to avoid impl repetition (especially for primitive types), so you don't need to feel dirty !: P

+4
source

Macros are currently the only way to do this. Coherence rules prevent multiple implementations that may overlap, so you cannot use a common solution.

+3
source

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


All Articles