(Rust)是否有一种方法可以为过载的操作员自动借用?
我试图在Rust中实现一个基本的多项式类型,使用重载运算符进行数学运算。到目前为止,我可以通过重载操作符来实现加法、减法等基本操作。问题是,我希望通过引用获取操作数,以避免不必要的复制。即。 :(Rust)是否有一种方法可以为过载的操作员自动借用?,rust,Rust,我试图在Rust中实现一个基本的多项式类型,使用重载运算符进行数学运算。到目前为止,我可以通过重载操作符来实现加法、减法等基本操作。问题是,我希望通过引用获取操作数,以避免不必要的复制。即。 : impl ops::Add for &Polynomial { type Output = Polynomial; fn add(self, other: Self) -> Polynomial { let mut result = self.clone()
impl ops::Add for &Polynomial {
type Output = Polynomial;
fn add(self, other: Self) -> Polynomial {
let mut result = self.clone();
for (power, coeff) in other.coefficients.iter().enumerate() {
result.add_coeff(power, *coeff);
}
result
}
}
impl ops::Sub for &Polynomial {
// Implementation
// ...
}
impl ops::Mul for &Polynomial {
// Implementation
// ...
}
// Etc.
这与预期的一样有效,但是它强制用户每次都显式借用操作数,随着表达式变得更复杂,可读性会降低 :
let (quotient, remainder) = p2.div_rem(&p1);
assert_eq!(&("ient * &p1) + &remainder, p2);
// Even worse example found on the internet.
// Note that you need to explicitly borrow each and every intermediate result :
let result = &(&(&a * &b) + &(&c * &d)) / 2;
我想,如果我能写的话,它会更清晰易读,而不是最后两行 :
assert_eq!(quotient * p1 + remainder, p2);
let result = (a * b + c * d) / 2;
…让借款发生« 自动地 »(就像调用一个方法时一样,该方法将&self
作为任何值的第一个参数 : 它是自动和隐式借用的,而无需显式借用)
然而,我不知道这是否可能,或者如何做到 ?> AfAIK,不,没有简单的方法来做这件事,因为锈设计引用总是明确的,从不隐含的,这是因为两种设计选择(即避免了C++引用的相同设计问题,这是奇怪的)和必要性(由于借阅检查器)。
T,&T,&mut T T,*const T
。。。都是具有不同语义的不同类型,因此允许impl-ops::Add-for&polymone
也适用于polymone
,基本上意味着impl-ops::Add-for&T
将自动实现ops::Add
forT
,这可能会导致非常奇怪且可能不安全的结果,尤其是如果相反的情况也是如此。那么&mut
呢?&mut T
是否会自动衰减为&
,对借书本身的寿命有何影响
此外,在非
复制值类型上实现ops::Add
是非常奇怪的,因为运算符会导致其操作数移入-这肯定不是人们在大多数情况下使用+
时所期望的。标准方法是为引用和值定义算术运算。这对于实现来说可能有点乏味(通常涉及宏以减少代码重复),但为API用户提供了最大的可用性
然后,用户可以编写外观规则的代码,而无需额外借用,但也可以在希望保留值供以后使用时选择借用(从而避免不必要的复制)。例如,使用num_bigint
板条箱,所有这些工作:
assert!(BigUint::from(1u8) + BigUint::from(1u8) == BigUint::from(2u8));
assert!(&BigUint::from(1u8) + &BigUint::from(1u8) == BigUint::from(2u8));
assert!(BigUint::from(1u8) + &BigUint::from(1u8) == BigUint::from(2u8));
assert!(&BigUint::from(1u8) + BigUint::from(1u8) == BigUint::from(2u8));
是的,在这种情况下,理论理想(“我想要+
和-
关于多项式的
”)会冲向实用(“但它们不是复制
,所以很奇怪”)和Rust,作为一种低级语言,落在这种二分法的实用方面。谢谢你的回答。然而,我不确定我是否理解你的最后一段。当人们添加两个值时,即让c=a+b
他们期望值a
和b
在操作后仍然可用,并且不会被使用(这样您也可以在同一表达式中使用相同的值两次,即让c=a*a;
),但我不明白为什么它会排除非复制类型,如果我们可以通过引用将值提供给运算符 ? 事实上,当我看到常见运算符(即+,-,*,/,%)一开始就没有引用时,我感到很惊讶,因为这个确切的原因。此外,实现ops::Add-on非复制值类型非常奇怪,由于运算符导致其操作数被移入-这绝对不是人们在大多数情况下使用+时所期望的事实并非如此,bigint板条箱往往同时实现这两种功能,是的,+
和-
确实可以移动东西。()请注意,这是一个非复制的函数,它实现了Add
,通过值获取LHS,通过引用获取RHS。@user4815162342实现这两个函数并没有改变我所说的,它仍然让它变得奇怪,因为通常人们希望在进行求和或减法后两个操作数仍然可用。在大多数人的心目中,他们不是破坏性的操作员,他们本能地期望他们的行为就像他们是根据参考文献定义的一样。