Jer*_*sen 40 reference traits lifetime rust
我做了一个两元素Vector结构,我想重载+运算符.
我使我的所有函数和方法都采用引用而不是值,我希望+运算符以相同的方式工作.
impl Add for Vector {
fn add(&self, other: &Vector) -> Vector {
Vector {
x: self.x + other.x,
y: self.y + other.y,
}
}
}
Run Code Online (Sandbox Code Playgroud)
根据我尝试的变化,我要么遇到生命问题,要么输入不匹配.具体来说,这个&self论点似乎没有被视为正确的类型.
我已经看到了模板参数的例子上impl,以及Add,但他们只是导致不同的错误.
我发现如何为不同的RHS类型和返回值重载运算符?但即使我把一个use std::ops::Mul;放在顶部,答案中的代码也不起作用.
我正在使用rustc 1.0.0-nightly(ed530d7a3 2015-01-16 22:41:16 +0000)
我不接受"你只有两个字段,为什么要使用参考"作为答案; 如果我想要一个100元素结构怎么办?我会接受一个答案,证明即使有一个大的结构我也应该通过值传递,如果是这样的话(我认为不是这样).我有兴趣知道结构大小的一个好的经验法则并且通过值vs struct传递,但这不是当前的问题.
Fra*_*gné 53
你需要实现Addon &Vector而不是on Vector.
impl<'a, 'b> Add<&'b Vector> for &'a Vector {
type Output = Vector;
fn add(self, other: &'b Vector) -> Vector {
Vector {
x: self.x + other.x,
y: self.y + other.y,
}
}
}
Run Code Online (Sandbox Code Playgroud)
在其定义中,Add::add总是self取值.但引用类似于任何其他类型1,因此它们也可以实现特征.当在引用类型上实现特征时,类型self是引用; 引用按值传递.通常,在Rust中传递值意味着转移所有权,但是当引用按值传递时,它们只是被复制(或者如果它是可变引用则被重新借用/移动),并且不会转移引用的所有权(因为引用)首先不拥有它的指示物).考虑到所有这些,Add::add(以及许多其他运算符)self按值获取是有意义的:如果您需要获取操作数的所有权,则可以实现Add直接在结构/枚举上,如果不是,可以Add在引用上实现.
这里self是类型&'a Vector,因为这是我们正在实现的类型Add.
请注意,我还指定了RHS具有不同生命周期的type参数,以强调两个输入参数的生命周期不相关的事实.
1实际上,引用类型的特殊之处在于,您可以实现对包中定义的类型的引用的特征(即,如果您被允许实现特征T,那么您也可以实现它&T).&mut T并且Box<T>具有相同的行为,但是对于未在同一个箱中定义的U<T>地方而言,这通常不正确U.
如果要支持所有方案,则必须支持所有组合:
在防锈方面,这是通过内部宏完成的。
幸运的是,有一个防锈板条箱impl_os,它还提供了一个宏来为我们编写样板:板条箱提供了impl_op_ex!宏,生成所有组合。
这是他们的样本:
#[macro_use] extern crate impl_ops;
use std::ops;
impl_op_ex!(+ |a: &DonkeyKong, b: &DonkeyKong| -> i32 { a.bananas + b.bananas });
fn main() {
let total_bananas = &DonkeyKong::new(2) + &DonkeyKong::new(4);
assert_eq!(6, total_bananas);
let total_bananas = &DonkeyKong::new(2) + DonkeyKong::new(4);
assert_eq!(6, total_bananas);
let total_bananas = DonkeyKong::new(2) + &DonkeyKong::new(4);
assert_eq!(6, total_bananas);
let total_bananas = DonkeyKong::new(2) + DonkeyKong::new(4);
assert_eq!(6, total_bananas);
}
Run Code Online (Sandbox Code Playgroud)
更好的是,它们具有impl_op_ex_commutative!如果您的运算符恰好是可交换的,那么也会生成带有相反参数的运算符。