微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

从特征函数返回复制值的迭代器

如何解决从特征函数返回复制值的迭代器

我要求 trait 有一个函数,该函数返回某个值类型的迭代器。实现此 trait 的结构可能只是存储我们想要迭代的(只读)值集合。

我在下面尝试了一个人为的例子:

use std::iter::copied;
use std::collections::{hash_set,HashSet};

trait MyTrait<I: IntoIterator<Item = usize>> {
    fn iter(&self) -> I;
}

struct MyStruct{
    set: HashSet<usize>,}

type Iter<'a> = copied<hash_set::Iter<'a,usize>>;

impl MyTrait<Iter<'_>> for MyStruct {
    fn iter(&self) -> Iter<'_> {
        self.set.iter().copied()
    }
}

但是,上面的代码会产生以下编译器错误

error: `impl` item signature doesn't match `trait` item signature
  --> src/lib.rs:15:5
   |
5  |     fn iter(&self) -> I;
   |     -------------------- expected `fn(&MyStruct) -> copied<std::collections::hash_set::Iter<'_,usize>>`
...
15 |     fn iter(&self) -> Iter<'_> {
   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^ found `fn(&MyStruct) -> copied<std::collections::hash_set::Iter<'_,usize>>`
   |
   = note: expected `fn(&MyStruct) -> copied<std::collections::hash_set::Iter<'_,_>>`
              found `fn(&MyStruct) -> copied<std::collections::hash_set::Iter<'_,_>>`
help: the lifetime requirements from the `impl` do not correspond to the requirements in the `trait`
  --> src/lib.rs:5:23
   |
5  |     fn iter(&self) -> I;
   |                       ^ consider borrowing this type parameter in the trait

“预期”和“发现”看起来相同,所以这可能是匿名生命周期的问题?我怎样才能让它工作?

Link to playground

解决方法

问题是编译器不能在这里推断出正确的生命周期,所以你需要告诉它它们是什么,像这样:

impl<'a> MyTrait<Iter<'a>> for MyStruct {
    fn iter(&'a self) -> Iter<'a> {
        self.set.iter().copied()
    }
}

不幸的是,您不能这样做,因为 trait 对 self 没有生命周期要求,所以实现者也不能。为此,您可以简单地将特征更改为:

trait MyTrait<'a,I: 'a + IntoIterator<Item = usize>> {
    fn iter(&'a self) -> I;
}

这里的 I: 'a + ... 告诉编译器,I 中的任何引用都可能比 'a 存活时间更长,即 self

现在您可以像这样实现 MyTrait

impl<'a> MyTrait<'a,Iter<'a>> for MyStruct {
    fn iter(&'a self) -> Iter<'a> {
        self.set.iter().copied()
    }
}

对于生命周期真的无关紧要的类型,因为 I 实际上不包含任何引用,您仍然可以使用生命周期省略:

impl MyTrait<'_,std::vec::IntoIter<usize>> for Vec<usize> {
    fn iter(&self) -> std::vec::IntoIter<usize> {
        self.clone().into_iter()
    }
}

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。