我有一个结构,它实现了几个运算符:
use std::ops;
/// Vector of 3 floats
#[derive(Debug, Copy, Clone)]
pub struct Vec3 {
pub x: f32,
pub y: f32,
pub z: f32,
}
/// Add operator
impl ops::Add<&Vec3> for &Vec3 {
type Output = Vec3;
#[inline(always)]
fn add(self, rhs: &Vec3) -> Self::Output {
Vec3 {
x: self.x + rhs.x,
y: self.y + rhs.y,
z: self.z + rhs.z,
}
}
}
/// Subtract operator
impl ops::Sub<&Vec3> for &Vec3 {
type Output = Vec3;
#[inline(always)]
fn sub(self, rhs: &Vec3) -> Self::Output {
Vec3 {
x: self.x - rhs.x,
y: self.y - rhs.y,
z: self.z - rhs.z,
}
}
}
/// Scalar multiplication operator
impl ops::Mul<&Vec3> for f32 {
type Output = Vec3;
#[inline(always)]
fn mul(self, rhs: &Vec3) -> Self::Output {
Vec3 {
x: self * rhs.x,
y: self * rhs.y,
z: self * rhs.z,
}
}
}
我想使用运营商:
let a = Vec3 { x: 0.0, y: 0.5, z: 1.0 };
let b = Vec3 { x: 1.0, y: 0.5, z: 0.0 };
let c = Vec3 { x: 1.0, y: 1.0, z: 0.0 };
let d = Vec3 { x: 0.0, y: 1.0, z: 1.0 };
let result = 2.0 * (a + b) - 3.0 * (c - d);
此代码将不会编译,因为运算符是为&Vec3
实现的,而不是为Vec3
实现的。为了解决这个问题,最后一行必须是这样的:
let result = &(2.0 * &(&a + &b)) - &(3.0 * &(&c - &d));
看起来不再那么好看了。
我知道我可以实现Vec3
的运算符来避免这个问题,但如果我仍然想在堆栈上使用对这些向量的不可变引用呢?有没有一种方法可以给Rust一些提示,如果我写a + b
,而Vec3 + Vec3
没有运算符,它可以尝试寻找&Vec3 + &Vec3
运算符,如果找到,则自动为两个参数获取不可变的引用?
不,当添加两个值时,没有办法自动获取引用。
我想,你可以编写自己的宏来实现这一点。在使用中,它看起来像:
thing!{ a + b }
// expands to
(&a + &b)
我预计这个宏会很快变得令人厌倦。
另请参阅:
- 允许运算符中的autoderef和autoref——RFC#2147
- 跟踪问题:允许运算符中的autoderef和autoref(实验(#44762
- 打印!借用还是拥有变量
- 如何在Rust中实现值和引用的惯用运算符重载
- 运算符按值重载导致使用移动的值
- 如何为引用类型实现Add这样的运算符,以便一次添加两个以上的值