generics - 如何在不使用克隆的情况下编写保持状态并返回值的通用迭代器?

标签 generics rust iterator clone

我试图编写一个通用迭代器,但我不知道如何在不使用 clone 的情况下返回值。有没有办法在 next 函数中创建一个变量并返回一个引用?如果我用 u32 替换 T,那么我可以只返回 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"),
    }
}

最佳答案

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

另一方面,真正的问题在于:

If I replace T with u32, then I can just return Some(self.count), but using generics, it is not possible.

这只是因为 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())
    }
}

另见:

关于generics - 如何在不使用克隆的情况下编写保持状态并返回值的通用迭代器?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/54835700/

相关文章:

c# - 展平 IEnumerable<IEnumerable<>>;理解泛型

java - <T extends Object & E> vs <T extends E>

c++ - 通过 Rust 中的泛型类型进行编译时算术,类似于 C++?

rust - 如何在 Option<T> 中访问 T 而不会导致移动?

rust - 如何在方法实现中从枚举中的字符串返回 &str?

c++ - 大写字母

c# - 为什么 IsGenericParameter 对于泛型参数为假 T

带有 Protocol.Type 的 Swift 泛型

java - 迭代所有相同类型的连接 block

c++ - 为什么 std::set.insert() 返回一个非常量迭代器,但我无法修改它?