我还是很陌生。我想使用一个变量在返回不同类型结构的几个函数之一中进行选择,但是所有这些函数都具有相同的特征。然后,我想将返回的结构从所选函数传递给某些函数,这些函数旨在接受具有该特征的任何变量。但是,我不知道如何去做。我已经读过How do I overcome match arms with incompatible types for structs implementing same trait?,但是由于我仍然无法正常工作,所以我错过了一些东西。我将返回值传递给的函数不接受该值-参见下文。
这是使用上面链接中的一种方法的简化示例:
trait IsEven {
fn is_even(&self) -> bool;
}
struct First {
v: u8,
}
impl IsEven for First {
fn is_even(&self) -> bool {
self.v % 2 == 0
}
}
struct Second {
v: Vec<u8>,
}
impl IsEven for Second {
fn is_even(&self) -> bool {
self.v[0] % 2 == 0
}
}
fn make1() -> First {
First{v: 5}
}
fn make2() -> Second {
Second{v: vec![2, 3, 5]}
}
fn requires_is_even(v: impl IsEven) {
println!("{:?}", v.is_even());
}
fn main() {
for i in 0..2 {
let v1;
let v2;
let v = match i {
0 => {
v1 = make1();
&v1 as &IsEven
}
_ => {
v2 = make2();
&v2 as &IsEven
}
};
requires_is_even(v); // This is where it fails
}
}
在这种情况下,我得到的错误是:
52 | requires_is_even(v);
| ^^^^^^^^^^^^^^^^ the trait `IsEven` is not implemented for `&dyn IsEven`
在上面链接的其他一些示例中,我也尝试使用Box,但是仍然无法正常使用。有人可以帮忙吗?
谢谢
鲍勃
答案 0 :(得分:1)
requires_is_even
会收到一个按值实现IsEven
的对象,尽管该特征上的所有方法都通过共享引用获取self
。但是,尽管如此,&dyn IsEven
并不会自动实现IsEven
(尽管我们可以自己添加该实现,请参见下文)。
您在这里有几个选择:
更改该函数,以通过共享引用接收实现IsEven
的对象。 (此版本执行静态调度。)
fn requires_is_even(v: &(impl IsEven + ?Sized)) {
println!("{:?}", v.is_even());
}
注意:这里的?Sized
边界是必需的,因为参数位置的impl Trait
是类型参数的语法糖,并且类型参数具有隐式的Sized
绑定。
更改该函数以通过共享引用接收IsEven
特征对象。 (此版本具有动态调度功能。)
fn requires_is_even(v: &dyn IsEven) {
println!("{:?}", v.is_even());
}
对实现了IsEven
的类型的任何共享引用都实施IsEven
。
impl<T> IsEven for &T
where
T: IsEven + ?Sized
{
fn is_even(&self) -> bool {
(**self).is_even()
}
}
注意:通过添加约束?Sized
,此impl
也适用于&dyn IsEven
。特质对象(此处为dyn IsEven
,不是 &dyn IsEven
或Box<dyn IsEven>
)自动实现其对应的特征(如果特征为object-safe,则为特征对象类型完全不可用)。