一个结构包含一组我想让客户迭代的项目。这是一个尝试:
use std::collections::HashSet;
use std::hash::Hash;
pub struct Foo<T: Eq + Hash> {
items: HashSet<T>,
}
impl<'a, T: 'a + Eq + Hash> Foo<T> {
pub fn new() -> Self {
Foo {
items: HashSet::new(),
}
}
pub fn iterate<I>(&self) -> I
where
I: IntoIterator<Item = &'a T>,
{
self.items.iter()
}
}
这无法编译,并显示错误:
error[E0308]: mismatched types
--> src/lib.rs:19:9
|
15 | pub fn iterate<I>(&self) -> I
| - expected `I` because of return type
...
19 | self.items.iter()
| ^^^^^^^^^^^^^^^^^ expected type parameter, found struct `std::collections::hash_set::Iter`
|
= note: expected type `I`
found type `std::collections::hash_set::Iter<'_, T>`
= help: type parameters must be constrained to match other types
= note: for more information, visit https://doc.rust-lang.org/book/ch10-02-traits.html#traits-as-parameters
例如在for循环内,HashSet::iter
方法的返回值看起来像Iterator
。在我的iterate
方法中似乎可以进行某种类型的强制转换,但显然编译器还有其他想法。
如何在从Iterator
迭代器返回返回值的同时,在函数中指定HashSet
的返回类型?
换句话说,我想将迭代委托给HashSet
。我想避免实现自定义迭代器来执行此操作,但是如果那是唯一的方式,则希望了解它的完成方式。我已经可以通过返回Box<dyn Iterator>
来使它正常工作,但是如果可以像this answer所述仅使用特征边界,我也想避免这种方法。
另一个要求:在特征上声明iterate
方法时,该方法必须有效。看来可以排除以下方法:
pub trait FooTrait {
fn iterate(&self) -> impl Iterator<Item=&T>;
}
答案 0 :(得分:0)
您要impl Iterator
:
impl<'a, T: 'a + Eq + Hash> Foo<T> {
// ...
pub fn iterate(&'a self) -> impl Iterator<Item = &'a T> {
self.items.iter()
}
}
Rust书中有this section对此进行了介绍。它在RFC 1522,RFC 1951和RFC 2071中定义和完善。尚未完成,有this tracking issue。