我如何告诉 Rust 某些东西实现了一个特征?

How do I tell Rust that something implements a trait?

我正在尝试编写一个 returns 迭代器的通用函数。

fn one_to_ten<T: Add>() -> std::iter::Iterator<Item = T> {
    (1..5).chain(5..=10)
}

它是通用的,因为它需要为 u8u128 工作,最好也为 i8i128 工作,对于以下代码:

let mut sum: u64 = 0;
for x in one_to_ten() {
    sum += x;
}

不幸的是,Rust 抱怨:

= help: the trait std::marker::Sized is not implemented for (dyn std::iter::Iterator<Item = T> + 'static)
error[E0277]: the size for values of type dyn std::iter::Iterator<Item = _> cannot be known at compilation time

error[E0308]: mismatched types
expected trait std::iter::Iterator, found struct std::iter::Chain

我在这里无法理解。当我试图实现一个通用函数时,Rust 似乎认为我正在尝试实现一个动态调度函数。 (并且,出于某种原因,我的链式迭代器不被接受为迭代器——我的猜测是我指定的是类型而不是特征,但是 std::iter::Iterator 是特征,而不是类型。)

我的代码应该是什么样的?

特征未确定大小,因此您不能 return 特征类型的值。相反,您必须 return 实现该特征的类型的值:

fn one_to_ten<T: Add>() -> impl std::iter::Iterator<Item = T> {
    (1..5).chain(5..=10)
}

不幸的是,这带来了另一个问题,即 (1..5) 代码构建了一个整数范围,而不是 T。您可以使用自定义特征来解决这个问题,因为 std::iter::Step 仍然不稳定。

类似于this (playground):

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 特性。