如何为引用类型实现类似于Add的运算符,以便一次添加两个以上的值? [英] How can I implement an operator like Add for a reference type so that I can add more than two values at once?

查看:115
本文介绍了如何为引用类型实现类似于Add的运算符,以便一次添加两个以上的值?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想创建一个不可变的,按引用的数据类型,并添加如下所示的内容:

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 Points:

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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆