进入结构类型的迭代器的通用生命周期参数

问题描述

我正在尝试创建一个数据结构(我们称之为 Outer)来包装另一个数据结构(我们称之为 Inner)。但是,我不想修复 Inner 的实现,而是想使用 trait,以便我可以轻松交换此底层数据结构的实现。

简化版本看起来有点像这样:

pub struct Outer<K,V,I>
where
    I: Inner<K,V>
{
    inner: I,// some phantom data fields
}

pub trait Inner<K,V>
{
    ...
}

现在,我想向 Outer 添加一个迭代器,它也应该包装内部数据结构提供的迭代器,问题来了。

Inner trait 中,我不能写:

fn iter(&self) -> impl Iterator<Item = (&'_ K,&'_ V)>;

as impl Trait 语法在这里是不允许的,我也不能引入像这样的关联类型:

type Iterator<'a>: Iterator<Item = (&'a K,&'a V)>;

因为 generic associated types 还没有出现。

到目前为止我想出的是为迭代器提供一个单独的特征:

pub trait InnerIterator<'a,K: 'a,V: 'a>: Iterator<Item = (&'a K,&'a V)> {
    type Inner: Inner<K,V>;

    fn new(inner: &'a Self::Inner) -> Self;
}

然后 Outer 接收一个新的泛型类型参数 InnerIt

pub struct Outer<K,I,InnerIt>
where
    I: Inner<K,// some phantom data fields
}

impl<K,InnerIt> Outer<K,InnerIt> {
    pub fn iter<'a>(&'a self) -> InnerIt
    where
        I: Inner<K,V>,InnerIt: InnerIterator<'a,K,Inner = I>,V: 'a,{
        InnerIt::new(&self.inner)
    }
}

现在,当我想选择一些特定的 Inner 实现时,我有类似的东西:

pub type SomeOuter<'a,V> = Outer<K,SomeInner<K,SomeInnerIterator<'a,V>>;

在这里,生命周期参数 'a 成为我的类型定义的一部分。

除了我必须添加至少两个参数来启用 iter_mutinto_iter 的问题之外,我的问题是在那里设置这个 'a 参数会产生什么后果,使用这种类型时它会继续传播吗,这种类型的用户会不会对这个生命周期参数感到惊讶,有没有办法实现迭代器而不引入泛型迭代器类型和 Outer 的生命周期?>

解决方法

使用这种类型会继续传播吗

任何想要嵌入你的类型的类型都需要有一个生命周期参数。 然而,有些地方终生省略会接管(例如在函数参数中):

struct Struct1<'a>(std::marker::PhantomData<&'a ()>);
struct Struct2<'a>(Struct1<'a>); // lifetime propagates to Struct2

fn func(_: Struct1){
    println!("lifetime not needed. It is 'elided'");
}

这种类型的用户会不会对这个生命周期参数感到惊讶

他们不应该。在 Rust 中,生命无处不在。例如,迭代切片是使用 struct with a lifetime parameter 完成的。

有没有一种方法可以在不为 Outer 引入泛型迭代器类型及其生命周期的情况下实现迭代器?

你有一个生命周期参数的原因是你有一个返回引用的迭代器。如果您的迭代器将返回一个直接对象,则不需要生命周期。例如,如果您将向量转换为迭代器(从而返回向量中的所有元素)it won't need a lifetime parameter