[英]Why are iterator items which are references not cast to a trait object reference?
我试图定义一个应该接收迭代器的函数,其中每个项目都是对特征对象的引用。 例如:
use std::fmt::Display;
fn show_items<'a>(items: impl Iterator<Item = &'a Display>) {
items.for_each(|item| println!("{}", item));
}
当我尝试在迭代器上调用它时,其中每个项目都是对实现Display
的类型的引用:
let items: Vec<u32> = (1..10).into_iter().collect();
show_items(items.iter());
我收到一个错误:
error[E0271]: type mismatch resolving `<std::slice::Iter<'_, u32> as std::iter::Iterator>::Item == &dyn std::fmt::Display`
--> src/lib.rs:9:5
|
9 | show_items(items.iter());
| ^^^^^^^^^^ expected u32, found trait std::fmt::Display
|
= note: expected type `&u32`
found type `&dyn std::fmt::Display`
note: required by `show_items`
--> src/lib.rs:3:1
|
3 | fn show_items<'a>(items: impl Iterator<Item = &'a Display>) {
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
为什么&u32
不被视为&dyn std::fmt::Display
?
显式强制转换可以正常工作:
show_items(items.iter().map(|item| item as &Display));
它也可以用于单个项目:
fn show_item(item: &Display) {
println!("{:?}", item);
}
let item: u32 = 1;
show_item(&item);
从类型的隐式转换T
到dyn Trait
的Trait
通过实施T
是所谓的未分级的强制 ,一种特殊形式的胁迫。 尽管Rust不太愿意使用隐式类型转换,但强制确实会在强制站点上隐式发生,而在其他地方却不会。
函数调用参数是强制站点。 这解释了为什么show_item()
函数可以show_item()
工作。
还可以使用as
运算符显式执行所有强制。 因此,使用map()
的版本可以正常工作。
您对show_items()
定义,
fn show_items<'a>(items: impl Iterator<Item = &'a Display>)
另一方面是完全不同的故事。 这里使用的impl
语法是的简写
fn show_items<'a, I>(items: I)
where
I: Iterator<Item = &'a dyn Display>,
该函数在迭代器类型上是通用的,并且编译器验证您实际传入的类型是否实现了特征绑定Iterator<Item = &'a dyn Display>
。 示例代码中的类型std::slice::Iter<'_, u32>
根本没有,因此出现错误。 没有强制将参数转换为其他类型以使其实现通用函数所需的某些特征绑定的强制转换。 还完全不清楚将std::slice::Iter<'_, u32>
转换为通过&dyn Display
进行迭代的类型。
请注意,您的函数定义版本由于需要对特征对象进行迭代而不必要地受到限制。 仅要求迭代器项改为实现Display
会更自然,更高效:
fn show_items<I>(items: I)
where
I: IntoIterator,
I::Item: Display,
(我也将Iterator
更改为IntoIterator
,因为这更通用,更方便。)
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.