实现Iterator时遇‘associated type not allowed here’错误的解决方法
如何实现只生成偶数索引元素的迭代器?
我想要将一个迭代器转换为只生成偶数索引元素的新迭代器,尝试了两种写法但都遇到了相同的错误:
第一种尝试代码
struct EvenIter<T, I: Iterator<Item = T>> { inner: I } impl<I, T> Iterator<Item = T> for EvenIter<T, I> { fn next(&mut self) -> Option<T> { let temp = self.inner.next(); let _ = self.inner.next(); temp } } pub fn evens<T>(iter: impl Iterator<Item = T>) -> impl Iterator<Item = T> { EvenIter { inner: iter } }
错误信息
error[E0229]: associated type bindings are not allowed here --> src/lib.rs:5:21 | 5 | impl<I, T> Iterator<Item = T> for EvenIter<T, I> { | ^^^^^^^^ associated type not allowed here
第二种尝试代码
struct EvenIter<T> { inner: dyn Iterator<Item = T> } impl<T> Iterator<Item = T> for EvenIter<T> { fn next(&mut self) -> Option<T> { let temp = self.inner.next(); let _ = self.inner.next(); temp } } pub fn evens<T>(iter: impl Iterator<Item = T>) -> impl Iterator<Item = T> { EvenIter { inner: iter } }
同样触发了上述相同错误。
错误原因
Rust不允许在impl语句的trait名称后直接绑定关联类型(比如Iterator<Item = T>这种写法),正确的方式是在impl块内部通过type Item = T;声明关联类型,或者通过泛型约束让编译器自动推导。
另外原代码的next逻辑存在小问题:如果第一次调用self.inner.next()返回None,此时再调用一次next()会无意义地跳过一个不存在的元素,需要加判断避免这种情况。
正确实现方式
方式一:使用泛型迭代器(推荐,无额外开销)
struct EvenIter<T, I: Iterator<Item = T>> { inner: I, } impl<I, T> Iterator for EvenIter<T, I> where I: Iterator<Item = T>, { // 显式声明关联类型Item为T type Item = T; fn next(&mut self) -> Option<T> { let temp = self.inner.next(); // 仅当当前元素存在时,才跳过下一个元素 if temp.is_some() { let _ = self.inner.next(); } temp } } pub fn evens<T>(iter: impl Iterator<Item = T>) -> impl Iterator<Item = T> { EvenIter { inner: iter } }
方式二:使用 trait 对象(适合需要类型擦除的场景)
如果需要对不同类型的迭代器做类型擦除,可以用Box<dyn Iterator>,但会带来轻微的运行时开销:
struct EvenIter<T> { // trait 对象必须放在指针类型中,比如Box inner: Box<dyn Iterator<Item = T>>, } impl<T> Iterator for EvenIter<T> { type Item = T; fn next(&mut self) -> Option<T> { let temp = self.inner.next(); if temp.is_some() { let _ = self.inner.next(); } temp } } pub fn evens<T>(iter: impl Iterator<Item = T> + 'static) -> impl Iterator<Item = T> { EvenIter { inner: Box::new(iter) } }
内容的提问来源于stack exchange,提问作者DanielSank
相关产品推荐
相关产品推荐

