我有一个函数,可以将特征作为参数包装在 Box
use std::fmt::Display;
fn push(e: Box<dyn Display>) {}
push(Box::new(0));
现在,我想创建另一个函数,该函数接受一个迭代器,其中每个Item都具有相同的类型
fn push_batch<I>(batch: I)
where
I: IntoIterator<Item = Box<dyn Display>>,
{
}
push_batch((0..10).map(|i| Box::new(i)));
但是这样做会导致以下错误:
error[E0271]: type mismatch resolving `<[closure@src/main.rs:13:28: 13:43] as FnOnce<({integer},)>>::Output == Box<(dyn std::fmt::Display + 'static)>`
--> src/main.rs:13:5
|
5 | fn push_batch<I>(batch: I)
| ---------- required by a bound in this
6 | where
7 | I: IntoIterator<Item = Box<dyn Display>>,
| ----------------------- required by this bound in `push_batch`
...
13 | push_batch((0..10).map(|i| Box::new(i)));
| ^^^^^^^^^^ expected integer, found trait object `dyn std::fmt::Display`
|
= note: expected struct `Box<{integer}>`
found struct `Box<(dyn std::fmt::Display + 'static)>`
= note: required because of the requirements on the impl of `Iterator` for `Map<std::ops::Range<{integer}>, [closure@src/main.rs:13:28: 13:43]>`
为什么第一个示例编译而第二个示例不编译?以及如何创建带框特征的迭代器以传递给push_batch
函数?
Rust不会自动转换Box<T>
为Box<dyn Trait>
,你必须明确地将其转换为:
push_batch((0..10).map(|i| Box::new(i) as Box<dyn Display>));
在第一种情况下会发生什么
push(Box::new(0));
?Rust推断类型为
Box<dyn Display>
,但是对于更复杂的表达式,尤其是涉及特征范围的表达式,类型推断开始失败。您也可以使用
Box::new(i) as _
。在这种情况下,Rust足够聪明,可以推断出所需的类型,它只是希望您阐明意图。知道在迭代器情况下是否有意(必须手动指定意图/广播),而在第一种情况下不必这样做是很有趣的。并且,如果这是故意的,或者实际上仅仅是编译器的限制。