如何实现 Mul Trait 以使自定义结构类型以两种方式工作

she*_*ath 4 rust trait-objects

// main.rs
#[derive(Clone, Copy)]
struct A(f64, f64);
impl<T> Mul<T> for A
where
    f64: From<T>,
    T: Copy, // f64: Mul<T>,
{
    type Output = A;
    fn mul(mut self, rhs: T) -> Self::Output {
        self.0 = self.0 * f64::from(rhs);
        self.1 = self.1 * f64::from(rhs);
        self
    }
}

impl Mul<A> for i32 {
    type Output = A;
    fn mul(self, mut rhs: A) -> Self::Output {
        rhs.0 = rhs.0 * f64::from(self);
        rhs.1 = rhs.1 * f64::from(self);
        rhs
    }
}

fn main() {
    let mut a = A(1.0, 1.0);
    a = a * 2;             // is fine
    a = a * 2.0;           // is fine
    a = a * 1 as u8;       // is fine

    a = 2 * a;             // is fine because I did implement for i32 type
    a = 2.0 * a;           // impl this with generic type!
}
Run Code Online (Sandbox Code Playgroud)

我可以使用通用参数Mul为我的结构实现 Trait ,AT

impl<T> Mul<T> for A
where
    f64: From<T>,
    T: Copy, 
{
    type Output = A;
    fn mul(mut self, rhs: T) -> Self::Output {
        self.0 = self.0 * f64::from(rhs);
        self.1 = self.1 * f64::from(rhs);
        self
    }
}
Run Code Online (Sandbox Code Playgroud)

现在我可以A与任何数字类型相乘,例如

A * f64或A * i32等等

但我无法使用Mul通用参数来实现 Trait,这使我可以这样做:

f64 * A和i32 * A

有没有办法像这样实现

impl Mul<A> for i32 {
    type Output = A;
    fn mul(self, mut rhs: A) -> Self::Output {
        rhs.0 = rhs.0 * f64::from(self);
        rhs.1 = rhs.1 * f64::from(self);
        rhs
    }
}
Run Code Online (Sandbox Code Playgroud)

但对于所有类型(通用参数)

impl<T> Mul<A> for T { // error:type parameter `T` must be covered by another type when it appears before the first local type
    type Output = A;
    fn mul(self, mut rhs: A) -> Self::Output {
        rhs.0 = rhs.0 * f64::from(self);
        rhs.1 = rhs.1 * f64::from(self);
        rhs
    }
}
Run Code Online (Sandbox Code Playgroud)

完整错误:

error[E0210]: type parameter `T` must be covered by another type when it appears before the first local type (`A`)
  --> src\main.rs:64:6
   |
64 | impl<T> Mul<A> for T {
   |      ^ type parameter `T` must be covered by another type when it appears before the first local type (`A`)
   |
   = note: implementing a foreign trait is only possible if at least one of the types for which it is implemented is local, and no uncovered type parameters appear before that first local type
   = note: in this case, 'before' refers to the following order: `impl<..> ForeignTrait<T1, ..., Tn> for T0`, where `T0` is the first and `Tn` is the last

For more information about this error, try `rustc --explain E0210`.
Run Code Online (Sandbox Code Playgroud)

orl*_*rlp 6

你不能。您只能对右侧参数进行泛型。

库通常如何解决这个问题是通用地实现它Self * T,然后创建一个宏来实现T* Self显Self * T式替换T它们支持的类型列表,例如nalgebra:

left_scalar_mul_impl!(u8, u16, u32, u64, usize, i8, i16, i32, i64, isize, f32, f64);
Run Code Online (Sandbox Code Playgroud)