gpt4 book ai didi

rust - 返回迭代器的特征

转载 作者:行者123 更新时间:2023-12-03 07:55:29 25 4
gpt4 key购买 nike

设置


假设我有以下特征 Stack它简单地定义了 poppush操作:

trait Stack<T> {
fn push(&mut self, data: T);
fn pop(&mut self) -> Option<T>;
}

我可以使用以下方法测试我的特征的任何给定实现:

fn test(stack: &mut dyn Stack<i32>) {
stack.push(1);
stack.push(2);
stack.push(3);

assert_eq!(stack.pop(), Some(3));
assert_eq!(stack.pop(), Some(2));
assert_eq!(stack.pop(), Some(1));
assert_eq!(stack.pop(), None);
}

例如,下面是一个在底层使用向量的实现:

struct StackWithVec<T> {
vec: Vec<T>,
}

impl<T> Stack<T> for StackWithVec<T> {
fn push(&mut self, data: T) {
self.vec.push(data);
}

fn pop(&mut self) -> Option<T> {
self.vec.pop()
}
}

我们可以使用 test 进行测试功能:

fn main() {
test(&mut StackWithVec {
vec: Vec::<i32>::new(),
})
}

这有效,一切都很好。

添加into_iter


现在假设我想向我的特质添加一个新函数 into_iter消耗 self并返回 Iterator<Item = T> :

trait Stack<T> {
fn push(&mut self, data: T);
fn pop(&mut self) -> Option<T>;
fn into_iter(self) -> dyn Iterator<Item = T>;
}

我尝试为我们的 StackWithVec 实现上述功能实现如下:

struct StackWithVecIntoIter<T>(StackWithVec<T>);

impl<T> Iterator for StackWithVecIntoIter<T> {
type Item = T;

fn next(&mut self) -> Option<Self::Item> {
self.0.pop()
}
}

impl<T> Stack<T> for StackWithVec<T> {
fn push(&mut self, data: T) {
self.vec.push(data);
}

fn pop(&mut self) -> Option<T> {
self.vec.pop()
}

fn into_iter(self) -> StackWithVecIntoIter<T> {
StackWithVecIntoIter(self)
}
}

但是编译器提示:

error[E0053]: method `into_iter` has an incompatible type for trait
--> src/main.rs:30:27
|
30 | fn into_iter(self) -> StackWithVecIntoIter<T> {
| ^^^^^^^^^^^^^^^^^^^^^^^
| |
| expected trait object `dyn Iterator`, found struct `StackWithVecIntoIter`
| help: change the output type to match the trait: `(dyn Iterator<Item = T> + 'static)`
|
note: type in trait
--> src/main.rs:4:27
|
4 | fn into_iter(self) -> dyn Iterator<Item = T>;
| ^^^^^^^^^^^^^^^^^^^^^^
= note: expected fn pointer `fn(StackWithVec<_>) -> (dyn Iterator<Item = T> + 'static)`
found fn pointer `fn(StackWithVec<_>) -> StackWithVecIntoIter<T>`

实现这种行为的正确方法是什么(通过修改特征或修改我的实现)?

最佳答案

Now let's say I want to add a new function to my trait into_iter that consumes self and returns an Iterator<Item = T>:

trait Stack<T> {
fn push(&mut self, data: T);
fn pop(&mut self) -> Option<T>;
fn into_iter(self) -> dyn Iterator<Item = T>;
}

这是关联类型的一个应用程序。将关联类型添加到 into_iter 返回的特征中:

trait Stack<T> {
type IntoIter: Iterator<Item = T>;

fn push(&mut self, data: T);
fn pop(&mut self) -> Option<T>;
fn into_iter(self) -> Self::IntoIter;
}

然后要实现它,您只需设置关联的类型:

impl<T> Stack<T> for StackWithVec<T> {
type IntoIter = StackWithVecIntoIter<T>;

fn push(&mut self, data: T) {
self.vec.push(data);
}

fn pop(&mut self) -> Option<T> {
self.vec.pop()
}

fn into_iter(self) -> Self::IntoIter {
StackWithVecIntoIter(self)
}
}

请注意,这本质上就是 IntoIterator trait works 的方式。 .

如果实际上是IntoIterator您正在使用,您可能只想制作 Stack一个subtraitIntoIterator :

trait Stack<T>: IntoIterator<Item = T> {
fn push(&mut self, data: T);
fn pop(&mut self) -> Option<T>;
}

关于rust - 返回迭代器的特征,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/76150373/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com