我有一个简单的 struct ,应该实现基本的数学运算符.最初,我不希望这些操作数消耗操作数,所以我实现了引用的特征,例如Add
:
impl<'a, 'b> Add<&'b MyType> for &'a MyType {
type Output = MyType;
fn add(self, rhs: &'b MyType) -> Self::Output {
// Implementation...
}
}
这允许我执行以下操作:
let result = &v1 + &v2;
其中v1
和v2
是类型MyType
.
然后我意识到,有时使用操作数在语法上更方便,例如在执行以下操作时:
let result = &v1 + &v2 + &v3;
因为有一个中间结果,所以上面的结果不会编译,您必须这样做:
let result = &v1 + &(&v2 + &v3);
所以我最终实现了Move和Borry的其他排列,它们只是遵循第一个排列:
impl<'a> Add<&'a MyType> for MyType {
type Output = MyType;
fn add(self, rhs: &'a MyType) -> Self::Output {
&self + rhs
}
}
impl<'a> Add<MyType> for &'a MyType {
type Output = MyType;
fn add(self, rhs: MyType) -> Self::Output {
self + &rhs
}
}
impl Add<MyType> for MyType {
type Output = MyType;
fn add(self, rhs: MyType) -> Self::Output {
&self + &rhs
}
}
这很管用,但很麻烦.
我寻找了一种更简单的方法,比如使用Borrow<T>
:
impl<B> Add<B> for B
where
B: Borrow<MyType>,
{
type Output = MyType;
fn add(self, rhs: B) -> Self::Output {
// Implementation...
}
}
但可以理解的是,由于type parameter
B must be used as the type parameter for some local type
,这不会编译.
有没有其他技巧可以避免所有这些针对Add
/Sub
/Mul
/Div
等的样板实现?
Update:个
@EvilTak在 comments 中提出了一个建议,通过在MyType
和&MyType
上明确实现B: Borrow<MyType>
版本来减少样板组合.这是一个很好的改进:
impl<'a, B> Add<B> for &'a MyType
where
B: Borrow<MyType>,
{
type Output = MyType;
fn add(self, rhs: B) -> Self::Output {
// Implementation...
}
}
impl<B> Add<B> for MyType
where
B: Borrow<MyType>,
{
type Output = MyType;
fn add(self, rhs: B) -> Self::Output {
&self + rhs
}
}