我试图用返回迭代器的函数构建一个特征。
我的简单示例如下:
pub trait TraitA {
fn things(&self) -> Iterator<Item=&u8>;
}
fn foo<A: TraitA>(a: &A) {
for x in a.things() { }
}
这不起作用,因为在编译时不知道迭代器大小类型。
答案 0 :(得分:7)
Rust的libstd有一个实现,即特征IntoIterator
。
/// Conversion into an `Iterator`
pub trait IntoIterator {
/// The type of the elements being iterated
type Item;
/// A container for iterating over elements of type `Item`
type IntoIter: Iterator<Item=Self::Item>;
/// Consumes `Self` and returns an iterator over it
fn into_iter(self) -> Self::IntoIter;
}
该特征具有这种特殊的按值(self
)公式,完全能够表达“迭代器”和“借用迭代器”语义。
由HashMap的IntoIterator
实现演示。 (他们使用hashmap的迭代器结构Iter
和IntoIter
。)这里有趣的是,为&HashMap<K, V, S>
类型实现了特征来表达“借用迭代器”。
impl<'a, K, V, S> IntoIterator for &'a HashMap<K, V, S>
where K: Eq + Hash, S: HashState
{
type Item = (&'a K, &'a V);
type IntoIter = Iter<'a, K, V>;
fn into_iter(self) -> Iter<'a, K, V> {
self.iter()
}
}
impl<K, V, S> IntoIterator for HashMap<K, V, S>
where K: Eq + Hash, S: HashState
{
type Item = (K, V);
type IntoIter = IntoIter<K, V>;
/// Creates a consuming iterator, that is, one that moves each key-value
/// pair out of the map in arbitrary order. The map cannot be used after
/// calling this.
fn into_iter(self) -> IntoIter<K, V> {
/* ... */
}
}
答案 1 :(得分:2)
基于另一个question,我认为最好的方法是将Iterator定义为特征类型,如下所示:
pub trait TraitA<'a> {
type I1: Iterator<Item=u8>;
type I2: Iterator<Item=&'a u8>;
fn iter_i1(&self) -> Self::I1;
fn iter_i2(&self) -> Self::I2;
}
fn foo<'a, A: TraitA<'a>>(a: &A) {
for x in a.iter_i1() { }
for x in a.iter_i2() { }
}