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

问题描述 投票:2回答:1

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

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

我可以这样做,其中abPoints:

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 * ca * b + c毕竟有不同的优先/解析树。有更好的方法吗?

我还想避免在非参考版本中进行不必要的复制。无论如何我正在返回一个新对象,所以首先克隆输入对我来说似乎是浪费时间。

rust add
1个回答
6
投票

我可能只是实现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)并从其余两个变体转发。

也可以看看:

© www.soinside.com 2019 - 2024. All rights reserved.