如何绑定高阶特征绑定生存期?



我有一个迭代器trait,它使用泛型关联类型来允许返回值引用迭代器拥有的数据:

pub trait MyIterator {
type T<'a>
where
Self: 'a;
fn next<'b>(&'b mut self) -> Option<Self::T<'b>>;
}

一个示例实现如下:

struct FooIterator<'counter> {
data: Vec<String>,
counter: &'counter AtomicU32,
index: usize
}
impl<'counter> MyIterator for FooIterator<'counter> {
type T<'d> = &'d str
where
Self: 'd;

fn next<'e>(&'e mut self) -> Option<Self::T<'e>> {
self.counter.fetch_add(1, Ordering::SeqCst);
self.index += 1;
Some(&self.data[self.index])
}
}

现在,我想有一个返回impl MyIterator对象而不使实现类型公开的工厂。然而,我不知道如何写生命周期。

我的第一次尝试是:

struct Factory {
data: Vec<String>,
counter: AtomicU32,
}
impl Factory {
fn new() -> Self {
Factory {
data: vec!["a".to_string(), "b".to_string(), "c".to_string(), "d".to_string()],
counter: AtomicU32::new(0),
}
}

fn create<'f>(&'f self) -> impl MyIterator<T<'_> = &'_ str> {
FooIterator {
data: self.data.clone(),
counter: &self.counter,
index: 0
}
}
}

但是,当尝试使用返回的迭代器时,会导致双重借用错误,如下所示:https://play.rust-lang.org/?version=nightly&mode=debug&edition=2021&gist=6490de8f21539537764d8f628454c5c1

接下来,我尝试使用更高级别的Trait边界,这似乎应该工作,但我不能得到以下编译,因为似乎'g不在where子句的范围内(https://play.rust-lang.org/?version=nightly&mode=debug&edition=2021&gist=beb46184de6f96bf83b64e838da4a335):

)
fn create<'f>(&'f self) -> impl for<'g> MyIterator<T<'g> = &'g str> + 'f where 'f: 'g {
FooIterator {
data: self.data.clone(),
counter: &self.counter,
index: 0
}
}

没有返回impl MyIterator代码工作正常,但我不想暴露FooIterator类型。看这个游乐场:https://play.rust-lang.org/?version=nightly&mode=debug&edition=2021&gist=2c595c136077791a692ea6e0a41c057c

你的问题在于MyIterator的定义,因为在那里next函数接受一个可变的借用到self,并返回一些与该可变借用一样存在的东西,这不是你期望从迭代器中得到的。

这是微妙的,因为它不会使代码不健全,它只是强制执行过多的约束,这反过来又使得不可能在不出错的情况下使用该特性。对MyIterator特性的生命周期进行了简单的重构,使其能够工作。看操场

最新更新