有没有办法不将迭代器的生命周期链接到结构体?

发布于 2025-01-19 21:53:21 字数 1635 浏览 3 评论 0原文

我正在尝试实现一个过滤器函数,该函数接收向量的迭代器并返回带有过滤器的迭代器。有什么方法可以不将迭代器的生命周期链接到结构体?我可以通过使迭代器的生命周期依赖于结构来使其工作,但这不是我打算做的。

这是一个简化的代码:

struct Structure {
    low: i32,
}

impl Structure {
    pub fn find_low<'a>(
        &mut self,
        packets: impl Iterator<Item = &'a i32>,
    ) -> impl Iterator<Item = &'a i32> {
        packets.filter(|packet| **packet < self.low)
    }

    pub fn new() -> Self {
        Structure { low: 10 }
    }
}

fn main() {
    let strct = Structure::new();
    let vec = [1, 2, 3, 11, 12, 13];
    let mut it = strct.find_low(vec.iter());
    assert_eq!(it.next().unwrap(), &vec[0]);
}

通过这样做,我收到错误

error[E0700]: hidden type for `impl Trait` captures lifetime that does not appear in bounds
 --> src/main.rs:9:10
  |
7 |         &mut self,
  |         --------- hidden type `Filter<impl Iterator<Item = &'a i32>, [closure@src/main.rs:10:24: 10:52]>` captures the anonymous lifetime defined here
8 |         packets: impl Iterator<Item = &'a i32>,
9 |     ) -> impl Iterator<Item = &'a i32> {
  |          ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  |
help: to declare that the `impl Trait` captures `'_`, you can add an explicit `'_` lifetime bound
  |
9 |     ) -> impl Iterator<Item = &'a i32> + '_ {
  |                                        ++++

游乐场

I am trying to implement a filter function which receives an iterator to a vector and returns an iterator with the filter. Is there any way by which I don't link the lifetime of the iterator to the struct? I am able to make it work by making lifetime of iterator depend on the struct but that is not what I intend to do.

Here is a simplified code:

struct Structure {
    low: i32,
}

impl Structure {
    pub fn find_low<'a>(
        &mut self,
        packets: impl Iterator<Item = &'a i32>,
    ) -> impl Iterator<Item = &'a i32> {
        packets.filter(|packet| **packet < self.low)
    }

    pub fn new() -> Self {
        Structure { low: 10 }
    }
}

fn main() {
    let strct = Structure::new();
    let vec = [1, 2, 3, 11, 12, 13];
    let mut it = strct.find_low(vec.iter());
    assert_eq!(it.next().unwrap(), &vec[0]);
}

By doing so, I get an error

error[E0700]: hidden type for `impl Trait` captures lifetime that does not appear in bounds
 --> src/main.rs:9:10
  |
7 |         &mut self,
  |         --------- hidden type `Filter<impl Iterator<Item = &'a i32>, [closure@src/main.rs:10:24: 10:52]>` captures the anonymous lifetime defined here
8 |         packets: impl Iterator<Item = &'a i32>,
9 |     ) -> impl Iterator<Item = &'a i32> {
  |          ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  |
help: to declare that the `impl Trait` captures `'_`, you can add an explicit `'_` lifetime bound
  |
9 |     ) -> impl Iterator<Item = &'a i32> + '_ {
  |                                        ++++

Playground

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

注定孤独终老 2025-01-26 21:53:21

是的,有一种方法不将返回的迭代器的生命周期链接到对 self 的引用的生命周期:您需要将过滤闭包所需的数据移动到闭包中,以便它不会引用它。要实现此目的,请将 self.low 复制到局部变量并将其移动到闭包中。

解决此问题后,您将发现第二个问题:您编写的 main() 无法将 strct.find_low() 调用为 strct未声明 mut ——但不需要如此。当不可变引用就可以时,find_low 不必要地将 self 作为可变引用。将 &mut self 替换为 &self

    pub fn find_low<'a>(
        &self,
        packets: impl Iterator<Item = &'a i32>,
    ) -> impl Iterator<Item = &'a i32> {
        let low = self.low;
        packets.filter(move |packet| **packet < low)
    }

Playground

另一种选择将 self.low 的副本移动到闭包中是为了限制其生命周期&self 也包含 'a,尽管这确实将返回的迭代器的生命周期链接到 Structure.

    pub fn find_low<'a>(
        &'a self,
        packets: impl Iterator<Item = &'a i32>,
    ) -> impl Iterator<Item = &'a i32> {
        packets.filter(move |packet| **packet < self.low)
    }

游乐场

Yes, there is a way not to link the lifetime of the returned iterator to that of the reference to self: you need to move the data the filtering closure needs into the closure so that it doesn't reference it. To accomplish this, copy self.low into a local variable and move it into the closure.

Once you fix this, you will uncover a second problem: your main() as written can't invoke strct.find_low() as strct is not declared mut -- but it shouldn't need to be. find_low needlessly takes self as a mutable reference, when an immutable reference will do. Replace &mut self with &self.

    pub fn find_low<'a>(
        &self,
        packets: impl Iterator<Item = &'a i32>,
    ) -> impl Iterator<Item = &'a i32> {
        let low = self.low;
        packets.filter(move |packet| **packet < low)
    }

(Playground)

An alternative to moving a copy of self.low into the closure is to restrict the lifetime of &self to include 'a as well, though this does link the lifetime of the returned iterator to that of Structure.

    pub fn find_low<'a>(
        &'a self,
        packets: impl Iterator<Item = &'a i32>,
    ) -> impl Iterator<Item = &'a i32> {
        packets.filter(move |packet| **packet < self.low)
    }

(Playground)

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文