简体   繁体   English

如何为数据结构实现非消耗可变 std::iter::Iterator

[英]How to implement a non-consuming mutable std::iter::Iterator for a data structure

I have a data structure called VecCircular and for a non-consuming immutable implementation of std::iter::Iterator, I followed the guidelines here .我有一个名为 VecCircular 的数据结构,对于 std::iter::Iterator 的非消耗不可变实现,我遵循了此处的指南。 here is my code:这是我的代码:

pub struct VecCircularIterator<'a, T> {
    vec_circular: &'a VecCircular<T>,
    index: usize,
}

impl<'a, T> std::iter::IntoIterator for &'a VecCircular<T> {
    type Item = &'a T;
    type IntoIter = VecCircularIterator<'a, T>;

    fn into_iter(self) -> Self::IntoIter {
        VecCircularIterator {
            vec_circular: &self,
            index: self.front_index,
        }
    }
}

impl<'a, T> std::iter::Iterator for VecCircularIterator<'a, T> {
    type Item = &'a T;
    fn next(&mut self) -> Option<&'a T> {
        if self.index == self.vec_circular.rear_index || self.vec_circular.empty() {
            return None;
        } else {
            let item = &self.vec_circular[self.index];
            self.index = (self.index + 1) % self.vec_circular.capacity;
            return Some(item);
        }
    }
}

but when I try to change that implementation to a mutable one:但是当我尝试将该实现更改为可变实现时:

pub struct VecCircularIterator<'a, T> {
    vec_circular: &'a mut VecCircular<T>,
    index: usize,
}

impl<'a, T> std::iter::IntoIterator for &'a VecCircular<T> {
    type Item = &'a T;
    type IntoIter = VecCircularIterator<'a, T>;

    fn into_iter(self) -> Self::IntoIter {
        VecCircularIterator {
            vec_circular: &mut self,
            index: self.front_index,
        }
    }
}

impl<'a, T> std::iter::Iterator for VecCircularIterator<'a, T> {
    type Item = &'a T;
    fn next(&mut self) -> Option<&'a T> {
        if self.index == self.vec_circular.rear_index || self.vec_circular.empty() {
            return None;
        } else {
            let item = &self.vec_circular[self.index];
            self.index = (self.index + 1) % self.vec_circular.capacity;
            return Some(item);
        }
    }
}

I get the following error:我收到以下错误:

    error[E0495]: cannot infer an appropriate lifetime for lifetime parameter in function call due to conflicting requirements
   --> src/queue/mod.rs:143:25
    |
143 |             let item = &self.vec_circular[self.index];
    |                         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    |
note: first, the lifetime cannot outlive the anonymous lifetime #1 defined on the method body at 139:5...
   --> src/queue/mod.rs:139:5
    |
139 | /     fn next(&mut self) -> Option<&'a T> {
140 | |         if self.index == self.vec_circular.rear_index || self.vec_circular.empty() {
141 | |             return None;
142 | |         } else {
...   |
146 | |         }
147 | |     }
    | |_____^
note: ...so that reference does not outlive borrowed content
   --> src/queue/mod.rs:143:25
    |
143 |             let item = &self.vec_circular[self.index];
    |                         ^^^^^^^^^^^^^^^^^
note: but, the lifetime must be valid for the lifetime `'a` as defined on the impl at 137:6...
   --> src/queue/mod.rs:137:6
    |
137 | impl<'a, T> std::iter::Iterator for VecCircularIterator<'a, T> {
    |      ^^
note: ...so that the types are compatible
   --> src/queue/mod.rs:139:41
    |
139 |       fn next(&mut self) -> Option<&'a T> {
    |  _________________________________________^
140 | |         if self.index == self.vec_circular.rear_index || self.vec_circular.empty() {
141 | |             return None;
142 | |         } else {
...   |
146 | |         }
147 | |     }
    | |_____^
    = note: expected  `std::option::Option<&'a T>`
               found  `std::option::Option<&T>`

error: aborting due to previous error

For more information about this error, try `rustc --explain E0495`.
error: could not compile `rudac`.

I'm a little shaky on rust lifetime parameters and I can't figure out what to do here.我对 rust 生命周期参数有点动摇,我不知道该怎么做。

An Iterator cannot yield borrowed values from within itself.迭代器不能从自身内部产生借来的值。 The API declaration for next would otherwise have to tie the Self::Item with a lifetime to self .否则, next的 API 声明必须将Self::Item与生命周期绑定到self

You could yield the value instead of a reference eg, something like this (but your code example is incomplete (missing VecCircular) so it's hard to guess what's a good way to do it):您可以产生值而不是引用,例如,像这样的东西(但是您的代码示例不完整(缺少 VecCircular),因此很难猜测什么是做这件事的好方法):

impl<T> std::iter::Iterator for VecCircularIterator<T> {
    type Item = T;
    fn next(&mut self) -> Option<T> {
        if self.index == self.vec_circular.rear_index || self.vec_circular.empty() {
            return None;
        } else {
            let item = self.vec_circular[self.index];
            self.index = (self.index + 1) % self.vec_circular.capacity;
            return item;
        }
    }
}

Also note that there is a problem with your into_iter method.另请注意,您的into_iter方法存在问题。 into_iter consumes self so if you assign a reference to vec_circular it will not live long enough (it goes out of scope once into_iter returns). into_iter消耗 self 因此,如果您分配对 vec_circular 的引用,它的寿命将不够长(一旦into_iter返回,它就会退出 scope )。

Btw.顺便提一句。 since it looks like you are implementing a queue on your own, you may also be interested in VecDeque from the standard library.因为看起来您正在自己实现一个队列,所以您可能也对标准库中的VecDeque感兴趣。 It also provides Iter , which can yield references.它还提供了Iter ,它可以产生引用。 It does that by not owning the VecDeque itself and instead just borrows a slice from it.它通过不拥有 VecDeque 本身来做到这一点,而只是从中借用一个切片。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM