Rust DRY traits 和 generics - impl Add 和 Mul 几乎相同

Rust DRY traits and generics - impl Add and Mul nearly identical

我有以下玩具代码,它使用泛型在 3d 向量上实现一些操作,作为 3 个泛型元素的结构。

use std::ops::Add;
use std::ops::Mul;

#[derive(Debug)]
pub struct Vec3<T> {
    x: T,
    y: T,
    z: T,
}

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

impl<T: Add<Output = T> + Copy> Add<T> for &Vec3<T> {
    type Output = Vec3<T>;
    fn add(self, other: T) -> Vec3<T> {
        Vec3 {
            x: self.x + other,
            y: self.y + other,
            z: self.z + other,
        }
    }
}

impl<T: Add<Output = T> + Copy> Add<&Vec3<T>> for &Vec3<T> {
    type Output = Vec3<T>;
    fn add(self, other: &Vec3<T>) -> Vec3<T> {
        Vec3 {
            x: self.x + other.x,
            y: self.y + other.y,
            z: self.z + other.z,
        }
    }
}

impl<T: Mul<Output = T> + Copy> Mul<T> for &Vec3<T> {
    type Output = Vec3<T>;
    fn mul(self, other: T) -> Vec3<T> {
        Vec3 {
            x: self.x * other,
            y: self.y * other,
            z: self.z * other,
        }
    }
}

impl<T: Mul<Output = T> + Copy> Mul<&Vec3<T>> for &Vec3<T> {
    type Output = Vec3<T>;
    fn mul(self, other: &Vec3<T>) -> Vec3<T> {
        Vec3 {
            x: self.x * other.x,
            y: self.y * other.y,
            z: self.z * other.z,
        }
    }
}

很明显,我所做的只是复制并粘贴我的 impl Add 并将 Add 替换为 Mul 并重命名方法名称。

这种轻微的重复让我想到了我的问题 - 生锈中是否有某种东西也概括了这一点?这类似于通用特征或 "meta trait"。在我的场景中,相关的 "meta trait" Op 会有一些方法 op。然后,不是实现 AddMul,而是实现 Opop 将分别取代 +* 运算符.

我探索并发现了超级特性,但我无法想象如何使用它们,因为我希望超越我想象的基本步骤:

trait Op<T>:Add<T>+Mul<T>{
    fn op(&self)->T;
}

关于您提出的有关二元运算的更一般特征的问题,该特征将为您创建 Add、Mul 等的含义:据我所知,有 none,我认为您不能 define it yourself 因为孤儿规则。你可以:

  • 为二进制操作特征写一个macro
  • 使用现有的 Vector3,例如 nalgebra 已经为您实现了这些特征的 Vector3
  • 尝试概括num_derive以处理具有多个成员的结构