返回特征函数复制值的迭代器
Returning iterator over copied values from trait function
我要求特征具有一个函数,该函数 returns 是某个值类型的迭代器。实现此特征的结构可以简单地存储我们要迭代的值的(只读)集合。
我在下面尝试了一个人为的例子:
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
“预期”和“找到”看起来相同,所以这可能是匿名生命周期的问题?我怎样才能让它工作?
问题是编译器无法在这里推断出正确的生命周期,因此您需要告诉它它们是什么,如下所示:
impl<'a> MyTrait<Iter<'a>> for MyStruct {
fn iter(&'a self) -> Iter<'a> {
self.set.iter().copied()
}
}
不幸的是,您不能这样做,因为该特征对 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()
}
}
我要求特征具有一个函数,该函数 returns 是某个值类型的迭代器。实现此特征的结构可以简单地存储我们要迭代的值的(只读)集合。
我在下面尝试了一个人为的例子:
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
“预期”和“找到”看起来相同,所以这可能是匿名生命周期的问题?我怎样才能让它工作?
问题是编译器无法在这里推断出正确的生命周期,因此您需要告诉它它们是什么,如下所示:
impl<'a> MyTrait<Iter<'a>> for MyStruct {
fn iter(&'a self) -> Iter<'a> {
self.set.iter().copied()
}
}
不幸的是,您不能这样做,因为该特征对 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()
}
}