【问题标题】:Return a reference to a member iterator返回对成员迭代器的引用
【发布时间】:2021-07-22 21:28:00
【问题描述】:

我有一个结构,它在借来的切片上有一个迭代器,我想创建一个方法,该方法返回一个迭代器,该迭代器对包含的迭代器进行一些计算

基本上是这样的:

#[derive(Clone)]
struct Foo<'a>  {
    inner: ::std::iter::Cycle<::std::slice::Iter<'a, u8>>,
}


impl<'a> Foo<'a> {
    pub fn new<T: AsRef<[u8]> + ?Sized>(vals: &'a T) -> Foo<'a> {
        Self {
            inner: vals.as_ref().iter().cycle(),
        }
    }
    pub fn iter(&mut self) -> impl Iterator<Item = u8> + 'a {
        self.inner.by_ref().map(Clone::clone) // simple case but this could be any computation
    }
}

这会产生一个神秘的错误。

这是我的理解:我需要将返回的迭代器的生命周期绑定到 iter()&amp;mut self,以便只有在返回的迭代器上调用 .collect() 时才会删除 &amp;mut self

但是,更改为 fn iter(&amp;'a mut self) 还不够好,因为 &amp;'a mut self 现在在结构实例的整个持续时间内都存在(这意味着调用 collect() 不会删除该引用)。这可以防止这样的事情

#[test]
fn test(){
    let mut foo = Foo::new("hello, there");
    foo.iter().zip(0..4).collect::<Vec<_>>(); // call once, ok
    foo.iter().zip(0..4).collect::<Vec<_>>(); // error because 2 &mut references exist at the same
}

锈游乐场link

【问题讨论】:

标签: rust


【解决方案1】:

我这样做的方法是创建一个结构体来迭代这些项目。它使事情变得更容易。

    ...

    pub fn iter(&mut self) -> ClonedFooIter<'a, '_> {
        ClonedFooIter {
            inner: &mut self.inner,
        }
    }
}

pub struct ClonedFooIter<'a, 'b> {
    inner: &'b mut std::iter::Cycle<::std::slice::Iter<'a, u8>>,
}

impl<'a, 'b> Iterator for ClonedFooIter<'a, 'b> {
    type Item = u8;

    fn next(&mut self) -> Option<Self::Item> {
        self.inner.next().cloned()
    }
}

这个想法是返回的结构只存在到self的可变借用存在。

使用结构也可以更轻松地命名迭代器类型。

【讨论】:

  • 您好,感谢您的回答,不幸的是,克隆不适用于我的用例,因为我需要 inner 有状态
猜你喜欢
  • 1970-01-01
  • 2017-03-20
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-05-09
  • 2015-01-30
相关资源
最近更新 更多