我想创建一个不可变的,引用数据类型,并添加如下:
use std::ops::Add;
struct Point {
x: i64,
y: i64,
}
impl<'a> Add for &'a Point {
type Output = Point;
fn add(self, other: &Point) -> Point {
Point {
x: self.x + &other.x,
y: self.y + &other.y,
}
}
}
How do I implement the Add trait for a reference to a struct?建议在参考类型上实施Add
。
我可以这样做,其中a
和b
是Point
s:
let c = &a + &b;
let d = &c + &b;
但不是这个:
let d = &a + &b + &b;
我不介意&
标志,但不能链添加对我来说不好看。我想实现乘法(z = a + b * c;
或者我必须,z = &a + &b * &c;
),如果我不必创建临时变量,它会更清晰。
有没有办法让它干净利落?包围似乎没有帮助。
我明白发生了什么,&a + &b
给了Point
而不是&Point
,这表明我可以实现add(&Point, Point)
和add(&Point, &Point)
- 但是现在共有4个案例可以让所有组合工作,因为a + b * c
和a * b + c
毕竟有不同的优先/解析树。有更好的方法吗?
我还想避免在非参考版本中进行不必要的复制。无论如何我正在返回一个新对象,所以首先克隆输入对我来说似乎是浪费时间。
我可能只是实现Add
对值的引用:
impl<'a> Add<&'a Point> for Point {
type Output = Point;
fn add(self, other: &'a Point) -> Point {
Point {
x: self.x + &other.x,
y: self.y + &other.y,
}
}
}
包围似乎没有帮助。
您可以参考表达式的一部分结果:
let d = &(&a + &b) + &b;
我不确定这对你来说是否更好看。
现在共有4例
实际上每次手术有4例:(T, T)
,(T, &T)
,(&T, T)
,(&T, &T)
。
有更好的方法吗?
不是真的,但这是因为你的下一个要求......
我还想避免在非参考版本中进行不必要的复制
这就是为什么操作按值消耗,以允许您重用任何潜在的分配。在Point
的情况下,它(ahem)毫无意义,因为结构是如此之小。像Vec
这样的类型更加可信。
所有这一切,人们通常使用宏来避免一遍又一遍地写同样的东西的苦差事。例如,standard library has a macro that assumes the types implement Copy
。但是,如果要重用分配,则意味着您不希望所有4个实现都相同。充其量你可以编写两个实现(&T, &T)
和(T, &T)
并从其余两个变体转发。
也可以看看: