如何在 Rust 中为引用创建“Iterable”特征?

Tun*_*coc 5 rust

我试图创建一个特点,抓住了iter在功能slice以及VecDequeBTreeMapHashMap。我希望这个特性的实现者能够指定和实现他们自己的迭代器类型,但看起来这个迭代器类型必须有一个生命周期参数,并且不能作为关联类型给出。

更详细地说,这是我希望在 Rust 中实现的功能:

trait RefIterable<T>
where for<'a> (T: 'a) => (Self::Iter<'a>: Iterator<Item = &'a T>)
{
  type Iter; // Has kind (lifetime -> type)
  fn refs<'a>(&'a self) -> Self::Iter<'a>
}
Run Code Online (Sandbox Code Playgroud)

如果这是可能的,实现可能看起来像这样

impl RefIterable<T> for Vec<T> {
  type Iter<'a> = std::slice::Iter<'a, T>; // This is not valid Rust code.
  fn refs<'a>(&'a self) -> std::slice::Iter<'a, T> {
    self.as_slice().iter()
  }
}
Run Code Online (Sandbox Code Playgroud)

我对 Rust 还是比较陌生,所以我问是否已经有一种我不知道的方法来做到这一点,或者是否有一种很好的解决方法来解决这种情况。我想这种情况并不少见。

(使用Box<dyn 'a + Iterator<Item = &'a T>>是我目前的解决方法,但这会阻止一些优化的发生。)

编辑:

EvilTak 的回答可能是我们现在能做的最好的事情。T: 'a到目前为止,Rust 似乎不支持将所有可能的生命周期与条件组合成一个非参数化特征的能力。

Evi*_*Tak 2

Iter相反,将生命周期参数添加到特征中,这允许您在关联类型的绑定中使用它:

trait RefIterable<'a> {
    type Item: 'a;
    type Iter: Iterator<Item = &'a Self::Item>; // Has kind (lifetime -> type)
    fn refs(&'a self) -> Self::Iter;
}
Run Code Online (Sandbox Code Playgroud)

需要使用界限Item: 'a来让编译器知道引用 ( &'a Self::Item) 的寿命不会比类型 ( Self::Item) 长。

我进行了修改RefIterable,使其遵循Iterator使用关联类型来指定迭代项目类型的约定,其原因与后面使用关联类型的原因相同。Iterator

实现非常简单:

impl<'a, T: 'a> RefIterable<'a> for Vec<T> {
    type Item = T;
    type Iter = std::slice::Iter<'a, T>;
    
    fn refs(&'a self) -> std::slice::Iter<'a, T> {
        self.as_slice().iter()
    }
}
Run Code Online (Sandbox Code Playgroud)

操场