实现Iterator时出现Rust类型错误

问题描述

我正在尝试将.split从切片推广到迭代器,而且似乎无法正确找到类型。这部分是因为我对Rust不太了解,部分是因为错误消息对于我从Rust看到的内容很奇怪。我已经包括了我认为是相关的代码片段,但是也有一个特征Splittable及其实现。错误(我相信第二个错误是由第一个错误引起的,如果不正确,请告诉我)

struct Split<I: Iterator,P: Fn(&I::Item) -> bool> {
    iter: I,pred: P,}

impl<I: Iterator,P: Fn(&I::Item) -> bool> Iterator for Split<I,P> {
    type Item = Vec<I::Item>;
    fn next(&mut self) -> Option<Self::Item> {
        self.iter
            .cloned()
            .position(|x| (self.pred)(&x))
            .map(|i| self.iter.take(i))
    }
}
error[E0271]: type mismatch resolving `<I as std::iter::Iterator>::Item == &_`
  --> src/main.rs:13:14
   |
13 |             .cloned()
   |              ^^^^^^ expected associated type,found reference
   |
   = note: expected associated type `<I as std::iter::Iterator>::Item`
                    found reference `&_`
   = note: consider constraining the associated type `<I as std::iter::Iterator>::Item` to `&_` or calling a method that returns `<I as std::iter::Iterator>::Item`
   = note: for more information,visit https://doc.rust-lang.org/book/ch19-03-advanced-traits.html

error[E0599]: no method named `position` found for struct `std::iter::Cloned<I>` in the current scope
   --> src/main.rs:14:14
    |
14  |               .position(|x| (self.pred)(&x))
    |                ^^^^^^^^ method not found in `std::iter::Cloned<I>`
    |
    = note: the method `position` exists but the following trait bounds were not satisfied:
            `<I as std::iter::Iterator>::Item = &_`
            which is required by `std::iter::Cloned<I>: std::iter::Iterator`

解决方法

您收到的特定错误消息是little misleading。真正令人抱怨的是,std::slice::cloned需要一个遍历引用的迭代器,您可以从其定义中看到它:

fn cloned<'a,T>(self) -> Cloned<Self>
where
    Self: Iterator<Item = &'a T>,T: 'a + Clone,

它需要一个对实现Clone的项目的引用上的迭代器(并且描述指出,将&T上的迭代器转换为T上的迭代器非常有用)。

但是,我怀疑您不是要克隆要迭代的项,而是要克隆迭代器本身。为此,您将使用clone方法而不是cloned,并且必须添加一个边界以确保迭代器是可克隆的,如下所示:

struct Split<I,P>
where
    I: Iterator + Clone,P: Fn(&I::Item) -> bool

您的代码中还有其他一些问题:

  • 您要多次借用self,才能访问iterpred
  • 您正在有效地将self.iter移到map内部的闭包中
  • take消耗了您调用它的迭代器,因此即使您重构以避免上述两个问题,它仍将无法编译。

如果您确实打算将实现限制为通过引用进行迭代,则可以这样定义范围:

struct Split<'a,I,T,P>
where
    I: Iterator<Item=&'a T>,P: Fn(&I::Item) -> bool

那么您将可以使用cloned

相关问答

错误1:Request method ‘DELETE‘ not supported 错误还原:...
错误1:启动docker镜像时报错:Error response from daemon:...
错误1:private field ‘xxx‘ is never assigned 按Alt...
报错如下,通过源不能下载,最后警告pip需升级版本 Requirem...