如何为引用类型实现像 Add 这样的运算符,以便可以一次添加两个以上的值?

2023-12-06

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

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,
        }
    }
}

如何实现结构体引用的 Add 特征?建议实施Add关于引用类型。

我可以做到这一点,在哪里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;),如果我不必创建临时变量,它看起来会更清晰。

有没有办法让它干净地工作?包围似乎没有帮助。

我明白发生了什么事&a + &b给出一个Point not a &Point,这表明我可以同时实现add(&Point, Point) and add(&Point, &Point)- 但现在总共有 4 种情况可以让所有组合发挥作用a + b * c and 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,这是毫无意义的,因为结构太小了。对于像这样的类型更可信Vec.


话虽如此,人们通常使用宏来避免一遍又一遍地编写相同内容的苦差事。例如,标准库有一个宏,假设类型实现Copy。如果你想reuse然而,分配意味着您不希望所有 4 个实现都相同。最好的情况是你可以编写两个实现(&T, &T) and (T, &T)并从其余两个变体向前推进。

也可以看看:

  • 如何实现结构体引用的 Add 特征?
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

如何为引用类型实现像 Add 这样的运算符,以便可以一次添加两个以上的值? 的相关文章

随机推荐