如何为引用类型实现类似于Add的运算符,以便一次添加两个以上的值? [英] How can I implement an operator like Add for a reference type so that I can add more than two values at once?
问题描述
我想创建一个不可变的,按引用的数据类型,并添加如下所示的内容:
I'd like to make an immutable, by-reference data type with addition a bit like this:
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,
}
}
}
我如何实现对结构的引用的添加特征?建议实现在引用类型上添加
。
我可以这样做,其中 a
和 b
是 Point
s:
I can do this, where a
and b
are Point
s:
let c = &a + &b;
let d = &c + &b;
但不是这样:
let d = &a + &b + &b;
我不介意&
的迹象,但无法链接添加对我来说并不好。我想实现乘法( z = a + b * c;
,或者如果必须的话, z =& a +& b *& c;
),如果我不必创建一个临时变量,则看起来会更清楚。
I don't mind the &
signs, but not being able to chain adds doesn't look good to me. I want to implement multiplication (z = a + b * c;
or if I must, z = &a + &b * &c;
), it would look clearer if I didn't have to create a temporary variable.
有没有办法将其转换为工作干净吗?括弧式包围似乎无济于事。
Is there a way to get this to work cleanly? Bracketing doesn't seem to help.
我知道发生了什么事,& a +& b
给出了 Point
而不是& Point
,这表明我可以同时实现 add(& ; Point,Point)
和 add(& Point,& Point)
-但现在总共有4种情况可以使所有组合正常工作因为 a + b * c
和 a * b + c
毕竟具有不同的优先级/解析树。还有更好的方法吗?
I understand what's going on, &a + &b
gives a Point
not a &Point
, which suggests that I could implement both add(&Point, Point)
and add(&Point, &Point)
- but now there are 4 cases in total to get all combinations working since a + b * c
and a * b + c
have different precedence / parse trees after all. Is there a nicer way?
我还希望避免在非参考版本中不必要的复制。无论如何我都会返回一个新对象,所以首先克隆输入对我来说似乎是浪费时间。
I'd also like to avoid unnecessary copying in the non-reference versions. I'm returning a new object anyway, so cloning the inputs first seems a waste of time to me.
推荐答案
我可能会只需实现对值的引用的 Add
:
I would probably just implement Add
of a reference to a value:
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,
}
}
}
括号似乎并没有帮助。
Bracketing doesn't seem to help.
您可以引用表达式的一部分结果:
You can take a reference to the result of part of the expression:
let d = &(&a + &b) + &b;
我不确定这对您来说是否更好。
I'm not sure if that looks better or not to you.
现在总共有4种情况
now there are 4 cases in total
实际上有4种情况每次操作:(T,T)
,(T,& T)
,(& T,T)
,(& T,& T)
。
There's actually 4 cases per operation: (T, T)
, (T, &T)
, (&T, T)
, (&T, &T)
.
有更好的方法吗?
Is there a nicer way?
不是真的,但这是因为您的下一个要求...
Not really, but that's because of your next requirement...
我还要避免在非引用版本中不必要的复制
I'd also like to avoid unnecessary copying in the non-reference versions
这就是为什么操作按值消耗的原因,以便您可以重用任何潜在的分配。在 Point
的情况下,这是(毫无意义的),因为结构非常小。像 Vec
这样的类型更可信。
That's why the operations consume by value, to allow you to reuse any potential allocations. In the case of the Point
, it's (ahem) pointless because the structs are so small. It's more believable for types like Vec
.
所有这些说,人们通常使用宏来避免一遍又一遍地写同一件事的繁琐工作。例如,标准库有一个假定类型实现 Copy
的宏。但是,如果要重用分配,则意味着您不希望所有4种实现都相同。充其量,您也许可以编写两个实现(& T,& T)
和(T,& T)
并从其余两个变体中转发。
All that being said, people usually use a macro to avoid the drudgery of writing the same thing over and over. For example, the standard library has a macro that assumes the types implement Copy
. If you want to reuse allocation, however, that means you do not want all 4 implementations to be the same. At best you might be able to write two implementations (&T, &T)
and (T, &T)
and forward from the remaining two variants.
另请参见:
- How do I implement the Add trait for a reference to a struct?
这篇关于如何为引用类型实现类似于Add的运算符,以便一次添加两个以上的值?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!