我正在尝试为实现另一特征的任何事物实现Add
特征(在示例代码中为Test
特征)。我在Add
实现中使用引用,因为并非所有实现Test
的东西都具有相同的大小。下面的代码可以正常编译:
use std::ops::Add;
struct Foo(i32);
struct Bar(i64);
trait Test {}
impl Test for Foo {}
impl Test for Bar {}
impl<'a, 'b> Add<&'b Test> for &'a Test {
type Output = Box<Test>;
fn add(self, other: &'b Test) -> Box<Test> {
if true {
Box::new(Foo(5))
} else {
Box::new(Bar(5))
}
}
}
如下所示,当我尝试实际使用Add
时,它说该操作无法应用,因为缺少Add
的{{1}}的实现。
&Foo
我对实现的定义有误吗?我打错了吗?目标是使函数add对实现了fn test_add() {
&Foo(5) + &Bar(5)
}
的对象进行两个引用,并返回对实现Test
的新对象的引用(或框)(并且可能不是相同的基础类型作为输入之一。
答案 0 :(得分:0)
我发现了另一种可以稍微改变行为但有效的方法。
struct V<T>(T);
use std::ops::Add;
impl<T1: Test, T2: Test> Add<V<Box<T2>>> for V<Box<T1>> {
type Output = V<Box<Test>>;
fn add(self, other: V<Box<T2>>) -> Self::Output {
unimplemented!()
}
}
这允许它返回实现Test
的任何类型,但代价是将所有内容包装在Box
和伪结构V
中。不是很优雅,我仍然不明白为什么我的原始代码不起作用,但是至少这具有我想要的行为。
答案 1 :(得分:0)
问题在于编译器无法从&Foo
隐式转换为&Test
。如果先将其明确转换为&Test
,则运算符重载将起作用:
fn test_add() {
let foo: &Test = &Foo(5);
foo + &Bar(5);
}
或者,您可以使用fully qualified syntax:
fn test_add() {
<&Test as Add<&Test>>::add(&Foo(5), &Bar(5));
}