【问题标题】:Why do I get the error "the trait `Iterator` is not implemented" for a reference to a generic type even though it implements IntoIterator?为什么即使它实现了 IntoIterator,对于泛型类型的引用,我也会收到错误“特征 `Iterator` 未实现”?
【发布时间】:2021-06-29 07:37:36
【问题描述】:

在以下示例中,MyTrait 扩展了 IntoIterator,但在循环中使用时编译器无法识别它。

pub trait MyTrait: IntoIterator<Item = i32> {
    fn foo(&self);
}

pub fn run<M: MyTrait>(my: &M) {
    for a in my {
        println!("{}", a);
    }
}

我得到错误:

error[E0277]: `&M` is not an iterator
 --> src/lib.rs:6:14
  |
6 |     for a in my {
  |              ^^ `&M` is not an iterator
  |
  = help: the trait `Iterator` is not implemented for `&M`
  = note: required because of the requirements on the impl of `IntoIterator` for `&M`
  = note: required by `into_iter`

【问题讨论】:

  • 仔细阅读错误信息:O 是可迭代的,但&amp;O 不是。
  • 我认为这是问题所在,但事实并非如此,我将 &V 替换为 &Vec 并且它有效
  • 那是因为&amp;Vec 实现了IntoIterator...
  • 这不仅仅是语法的怪癖:IntoIterator::into_iter() 接受self,即需要消耗它被调用的值。如果您只有一个对象的引用,那么它实现IntoIterator 的事实是没有用的,因为您不能使用引用来使用该对象。 &amp;Vec 提供了 IntoIterator 的单独实现,它简单地调用 self.iter() 并返回一个迭代器,该迭代器产生对向量元素的引用。
  • 所以我不确定如何解决它,我是否需要为&amp;OtherTrait 实现IntoIterator?

标签: rust traits


【解决方案1】:

只有M 实现了IntoIterator,但您尝试迭代&amp;M,这不是必须的。

尚不清楚您希望使用run 实现什么,但删除引用可能是一个开始:

pub fn run<M: MyTrait>(my: M) {
    for a in my {
        println!("{}", a);
    }
}

注意M它自己 可能是(或包含)一个引用,所以以这种方式编写它并不意味着您不能将它用于借来的数据。这是使用run 迭代&amp;Vec (playground) 的一种方法:

impl<I> MyTrait for I
where
    I: IntoIterator<Item = i32>,
{
    fn foo(&self) {}
}

fn main() {
    let v = vec![10, 12, 20];
    run(v.iter().copied());
}

这使用.copied() 将Iterator&lt;Item = &amp;i32&gt; 转换为Iterator&lt;Item = i32&gt;。

相关问题

【讨论】:

  • 但是@trentcl 这就是全部问题,即使我包装&amp;OtherTrait 我仍然需要以某种方式迭代&amp;OtherTrait
  • @GuyKorland 该问题没有包含足够的上下文来了解您如何尝试使用它。从 MyEnum is all you need to make your example compile 中删除 &amp;'a。我不知道您可能需要进行哪些其他更改才能编译其余代码,因为我不知道您的其余代码是什么样的。
  • 我要做的就是传递一个借来的特征并对其进行迭代。简化示例
  • @GuyKorland 简化示例的解决方案相同:just remove the &amp;。您不能通过引用使用IntoIterator。但是您可以仍然使用引用(以及包含引用的结构),这些引用本身实现了IntoIterator:for example, Copied&lt;Iter&lt;'_, i32&gt;&gt;。
  • 我或许应该补充一点,原则上您可以使用更高级别的特征绑定来解决此问题;然而,由于where clauses are only elaborated for supertraits,它是doesn't work today,即使它做到了,它仍然不能与M = Vec&lt;i32&gt;一起工作,因为&amp;Vec&lt;i32&gt;没有实现IntoIterator&lt;Item = i32&gt;(它实现了IntoIterator&lt;Item = &amp;i32&gt;——注意@987654356 @)。
猜你喜欢
  • 2018-05-24
  • 1970-01-01
  • 2023-03-29
  • 2018-10-04
  • 2021-07-02
  • 2020-03-02
  • 1970-01-01
  • 2018-08-05
相关资源
最近更新 更多