4

I am trying to implement a Vector struct. It is declared as follows:

use num_traits::Float;

pub struct Vec3<T> {
    pub x: T,
    pub y: T,
    pub z: T,
}

impl<T> Vec3<T>
where
    T: Float,
{
    pub fn new(x: T, y: T, z: T) -> Vec3<T> {
        Vec3 { x, y, z }
    }
}

I would like to have the ability to add an instance of this struct to a generic float value. I think in my case I would be anything that implements the Float trait:

let vec = Vec3::new(1.0, 1.0, 1.0);
let res = 1.0 + vec; // this should work for both f32 and f64

I was going to just implement the Add trait for Float, so I wrote:

use std::ops::Add;

impl<T: Float> Add<Vec3<T>> for T {
    type Output = Vec3<T>;

    fn add(self, other: Vec3<T>) -> Vec3<T> {
        Vec3::new(self + other.x, self + other.y, self + other.z)
    }
}

Which gives me the following error:

error[E0210]: type parameter `T` must be used as the type parameter for some local type (e.g. `MyStruct<T>`)
  --> src/lib.rs:20:1
   |
20 | impl<T: Float> Add<Vec3<T>> for T {
   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type parameter `T` must be used as the type parameter for some local type
   |
   = note: only traits defined in the current crate can be implemented for a type parameter

The closest related solution I could find online is the same that error message suggest: to wrap the Float trait with a struct, which does not fit with my requirements. I also tried to declare a local trait that contains Float, but that didn't really help.

Shepmaster
  • 388,571
  • 95
  • 1,107
  • 1,366
oniondomes
  • 2,034
  • 13
  • 22
  • why just don't implement Add in crate where you defined Vec3? Because as you can find [here](https://stackoverflow.com/questions/29789877/can-not-implement-trait-from-another-crate-for-generic-type-from-another-crate-p?rq=1) there is now way to do such thing in rust. – Ali Zeinali Feb 08 '19 at 23:06
  • @ali-zeinali thats's what I do. I'm not really sure, but I think the problem is I use `Float` trait wrong in this case. – oniondomes Feb 08 '19 at 23:07
  • would `let res = vec + 1.0` solve your problem? – Ali Zeinali Feb 08 '19 at 23:38
  • @AliZeinali I got this implementation, but I’d like it to work both ways. Thanks for the link btw. I’ll take a look – oniondomes Feb 08 '19 at 23:42
  • 2
    Seems it is impossible to use `let res = 1.0 + vec` because you have to implement `Add>` trait for `Float` while it's not allowed in rust – Ali Zeinali Feb 09 '19 at 00:09
  • And I don't understand while `let res = 1.0 + vec` would be same as `let res = vec + 1.0 ` why you insist to implement such a thing? – Ali Zeinali Feb 09 '19 at 00:16
  • @AliZeinali the idea behind that was the addition operation working both ways on primitives, so I though it would be nice to have the same behaviour on vectors as well – oniondomes Feb 09 '19 at 12:15

0 Answers0