Rust:无法将`Iterator<Item = Box<Dog>>`收集到`Vec<Box<dyn Animal>>`中。

3

我觉得这段代码应该可以工作,因为在大多数情况下,Box<Dog> 应该能够隐式转换为 Box<dyn Animal>

struct Dog {}
trait Animal {}
impl Animal for Dog {}

fn main() {
    let _: Vec<Box<dyn Animal>> = [Dog {}, Dog {}]
        .into_iter()
        .map(Box::new)
        .collect();
}

然而,我收到了以下编译器错误:
error[E0277]: a value of type `Vec<Box<dyn Animal>>` cannot be built from an iterator over elements of type `Box<Dog>`
    --> src/main.rs:9:10
     |
9    |         .collect();
     |          ^^^^^^^ value of type `Vec<Box<dyn Animal>>` cannot be built from `std::iter::Iterator<Item=Box<Dog>>`
     |
     = help: the trait `FromIterator<Box<Dog>>` is not implemented for `Vec<Box<dyn Animal>>`
     = help: the trait `FromIterator<T>` is implemented for `Vec<T>`
note: required by a bound in `collect`

For more information about this error, try `rustc --explain E0277`.

我也尝试插入.map(Into::into)以将Box<Dog>转换为Box<dyn Animal>,但是会出现错误the trait bound `Box<dyn Animal>: From<Box<Dog>>` is not satisfied(未满足“Box<dyn Animal>: From<Box<Dog>>”的特质限定)。那么我应该如何将我的Box<Dog>集合成Box<dyn Animal>呢?
1个回答

5

你已经接近成功了。问题在于Box::new()需要传入T类型的参数并返回一个Box<T>类型的值。没有类型强制转换可以实现。

相反地,你应该提供一个闭包|v| Box::new(v),但即使如此,编译器也不会立即意识到它需要进行强制转换,而当它意识到时,已经为时过晚(你可以在这里阅读更多内容)。你需要给出一些提示,使用简单的as就足够了:|v| Box::new(v) as _


我不知道这种语法存在!我一直使用 Box::<dyn T>::new(v) - ImajinDevon
@ImajinDevon 你不能这样做。而且这个语法并没有什么特别之处,只是使用了推断目标类型的 as 关键字。 - Chayim Friedman
我在某个地方做过类似的事情,只是找不到了。 - ImajinDevon
哦,太酷了!我的解决方案是 .map(|v| -> Box<dyn Animal> { Box::new(v) }),但是 as _ 更好。 - A. Kriegman
值得注意的是,将 Box<Dog> 强制转换为 Box<dyn Animal> 不是一个无操作,因此有时我们必须要有点显式。 - A. Kriegman

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接