如何编写保持状态并返回值而不使用clone的泛型迭代器?

问题描述 投票:1回答:1

我试着编写一个泛型迭代器,但我没有看到如何在不使用clone的情况下返回值。有没有办法在next函数中创建变量并返回引用?如果我用T替换u32,那么我可以返回Some(self.count),但是使用泛型,这是不可能的。

use num_traits::Num;
use std::clone::Clone;

struct Counter<T>
where
    T: Num + Clone,
{
    count: T,
}

impl<T> Counter<T>
where
    T: Num + Clone,
{
    fn new() -> Counter<T> {
        Counter { count: T::zero() }
    }
}

impl<T> Iterator for Counter<T>
where
    T: Num + Clone,
{
    type Item = T;

    fn next(&mut self) -> Option<Self::Item> {
        self.count = self.count.clone() + T::one();
        Some(self.count.clone())
    }
}

fn main() {
    let mut number: Counter<u32> = Counter::new();

    match number.next() {
        Some(x) => println!("Number {}", x),
        None => println!("Invalid"),
    }
}
generics rust iterator clone
1个回答
4
投票

一方面......不,你不能让迭代器返回对计数器值的引用。 Iterator::next()方法返回一个与接收器值&mut self没有生命周期连接的值,因此我们无法控制将在那里返回的引用的生命周期。这是必需的,因为我们无法在该引用借用时修改该值。另一个question更好地解释了这个问题。

另一方面,真正令人担忧的是:

如果我用T替换u32,那么我可以返回Some(self.count),但是使用泛型,这是不可能的。

这只是因为u32实现了Copy,这意味着只要有必要就会复制它。实现Copy的类型也实现了Clone,它与副本完全相同,这可能发生在非泛型上下文中。

因此,您在此处进行的克隆操作是合理的,因为您希望在仍拥有自己的状态时返回计数器的值。当该计数器的T是一个原始整数,如u32时,该克隆就像该整数的副本一样便宜。

除此之外,您可以在T上为AddAssign<T>添加约束,以便您可以使用+=运算符来递增内部状态。

impl<T> Iterator for Counter<T> where T: Num + Clone + AddAssign<T> {
    type Item = T;

    fn next(&mut self) -> Option<Self::Item> {
        self.count += T::one();
        Some(self.count.clone())
    }
}

也可以看看:

© www.soinside.com 2019 - 2024. All rights reserved.