【发布时间】:2021-05-26 12:22:45
【问题描述】:
我有一个结构,其中实现了几个运算符:
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 运算符,如果找到,获取不可变引用两个参数都自动?
【问题讨论】:
-
或者,您可以将 a,b,c,d 作为参考开始。
-
谢谢,确实如此。
+/-/*操作的中间结果仍然是Vec3s,所以该行看起来像let result = &(2.0 * &(a_ref + b_ref)) - &(3.0 * &(c_ref - d_ref)); -
通常为引用和拥有值实现二元运算符,例如对于
Vec3 + Vec3、&Vec3 + Vec3、Vec3 + &Vec3和&Vec3 + &Vec3。这样,所有中间结果都可以按值传递——无论如何移动它们都很好。连同让您的变量引用开始,这使您可以完全按照您想要的形式编写表达式。
标签: rust