我正在尝试编写一个返回迭代器的泛型函数。
fn one_to_ten<T: Add>() -> std::iter::Iterator<Item = T> {
(1..5).chain(5..=10)
}
之所以通用,是因为它需要为u8
至u128
工作,并且最好为i8
至i128
工作,适用于以下代码:
let mut sum: u64 = 0;
for x in one_to_ten() {
sum += x;
}
不幸的是,Rust抱怨:
=帮助:
std::marker::Sized
未实现特征(dyn std::iter::Iterator<Item = T> + 'static)
错误[E0277]:在编译时无法知道类型dyn std::iter::Iterator<Item = _>
的值的大小
和
错误[E0308]:类型不匹配
预期特征std :: iter :: Iterator,找到结构std::iter::Chain
我不在这里。当我尝试实现一个通用的函数时,Rust似乎认为我正在尝试实现一个动态调度的函数。 (并且由于某种原因,我的链式迭代器不被接受为迭代器–我的猜测是我指定的是类型而不是特征,但是std::iter::Iterator
是特征,而不是类型。)>
我的代码应该是什么样的?
答案 0 :(得分:3)
特征没有大小,因此您不能返回特征类型的值。相反,您必须返回实现该特征的类型的值:
fn one_to_ten<T: Add>() -> impl std::iter::Iterator<Item = T> {
(1..5).chain(5..=10)
}
不幸的是,这带来了另一个问题,(1..5)
代码生成的是整数范围,而不是T
的整数范围。您可以使用自定义特征来解决此问题,因为std::iter::Step
仍然不稳定。
pub trait MyRange: Sized {
type Iter: std::iter::Iterator<Item = Self>;
fn new(a: i32, b: i32) -> Self::Iter;
fn new_incl(a: i32, b: i32) -> Self::Iter {
Self::new(a, b + 1)
}
}
impl MyRange for i8 {
type Iter = std::ops::Range<Self>;
fn new(a: i32, b: i32) -> Self::Iter {
(a as i8 .. b as i8) //check overflow?
}
}
pub fn one_to_ten<T: Add + MyRange>() -> impl std::iter::Iterator<Item = T> {
T::new(1, 5).chain(T::new_incl(5, 10))
}
然后为您需要的每种整数类型实现MyRange
特性。