自定义SqIterator迭代器兼容filter等函数时遇类型不匹配错误求助
问题
我正尝试实现一个可与filter、map、flatmap等迭代器函数无缝配合的自定义迭代器SqIterator,但不确定当前实现是否正确。目前代码在Dasher的dash方法中出现类型不匹配错误:创建Sq2实例时,第二个参数是filter返回的Filter<SqIterator<T>, ...>类型,而Sq2要求参数为SqIterator<Iter<'_, Square>>类型。
相关代码
struct SqIterator<I>(I); impl<I> Iterator for SqIterator<I> where I: Iterator<Item = Square>, { type Item = I::Item; fn next(&mut self) -> Option<Self::Item> { self.0.next() } } impl<I: Iterator<Item = Square> + Clone> SqIterator<I> { fn new(iter: I) -> Self { SqIterator(iter) } fn into_a_pd(&self) -> impl Iterator<Item = (Square, BitboardPD)> { self.0.clone().flat_map(|a| Waypoint::a_square(a) .into_iter().map(move |pd| (a, pd))) } } struct Sq2<T>(SqIterator<T>, SqIterator<T>); struct Dasher; impl Dasher { /* P_k!!W */ fn no_dash<'a, T: Iterator<Item = Square> + Clone>(bs: &'a Bs, a: &'a SqIterator<T>, b: &'a SqIterator<T>) -> Sq2<T> { todo!() } fn dash<'a, T: Iterator<Item = Square> + Clone>(bs: &'a Bs, a: &'a SqIterator<T>, b: &'a SqIterator<T>) -> impl Iterator<Item = Sq2<T>> { a.into_a_pd().map(|(a, pd)| { let aa = SqIterator([a].iter()); let bb = b.filter(|&b| pd.dest.into() == b.pos); Sq2(aa, bb) }) } }
错误信息
error[E0308]: mismatched types --> src/gg.rs:106:15 | 105 | let bb = b.filter(|&b| pd.dest.into() == b.pos); | ---- the found closure 106 | Sq2(aa, bb) | --- ^^ expected `SqIterator<std::slice::Iter<'_, bitboard::Square>>`, found `Filter<SqIterator<T>, ...>` | | | arguments to this struct are incorrect | = note: expected struct `SqIterator<std::slice::Iter<'_, bitboard::Square>>` found struct `Filter<SqIterator<T>, [closure@src/gg.rs:105:25: 105:29]>` note: tuple struct defined here --> src/gg.rs:91:8 | 91 | struct Sq2<T>(SqIterator<T>, SqIterator<T>);
补充定义
#[derive(Copy, Clone)] struct Square { pos: u32, piece: u32 } struct BitboardPD { path: u32, dest: u32 } struct Bs; struct Waypoint; impl Waypoint { fn a_square(a: Square) -> Vec<BitboardPD> { vec![] } }
解决方案
问题根源
Sq2要求两个参数都是SqIterator<T>类型,但b.filter(...)返回的是标准库的Filter<SqIterator<T>, ...>迭代器适配器类型,并非自定义的SqIterator。aa的类型是SqIterator<std::slice::Iter<'_, Square>>,而未包装的bb类型与aa不匹配,导致Sq2的两个参数类型无法统一。
修改方案
- 为
SqIterator实现Fromtrait,方便将任意迭代器(包括标准库适配器)包装为SqIterator。 - 调整
Sq2的泛型约束,允许它接受两个不同底层类型的SqIterator,避免类型不匹配问题。
修正后代码
struct SqIterator<I>(I); impl<I> Iterator for SqIterator<I> where I: Iterator<Item = Square>, { type Item = I::Item; fn next(&mut self) -> Option<Self::Item> { self.0.next() } } // 实现From trait,快速将任意迭代器转为SqIterator impl<I: Iterator<Item = Square>> From<I> for SqIterator<I> { fn from(iter: I) -> Self { SqIterator(iter) } } impl<I: Iterator<Item = Square> + Clone> SqIterator<I> { fn new(iter: I) -> Self { SqIterator(iter) } fn into_a_pd(&self) -> impl Iterator<Item = (Square, BitboardPD)> { self.0.clone().flat_map(|a| Waypoint::a_square(a) .into_iter().map(move |pd| (a, pd))) } } // 修改Sq2,允许两个参数为不同底层类型的SqIterator struct Sq2<A, B>(SqIterator<A>, SqIterator<B>) where A: Iterator<Item = Square>, B: Iterator<Item = Square>; struct Dasher; impl Dasher { /* P_k!!W */ fn no_dash<'a, T: Iterator<Item = Square> + Clone>(bs: &'a Bs, a: &'a SqIterator<T>, b: &'a SqIterator<T>) -> Sq2<T, T> { todo!() } fn dash<'a, T: Iterator<Item = Square> + Clone>(bs: &'a Bs, a: &'a SqIterator<T>, b: &'a SqIterator<T>) -> impl Iterator<Item = Sq2<std::slice::Iter<'_, Square>, impl Iterator<Item = Square>>> { a.into_a_pd().map(|(a, pd)| { let aa = SqIterator::from([a].iter()); // 将filter返回的迭代器包装为SqIterator let bb = SqIterator::from(b.filter(|&b| pd.dest.into() == b.pos)); Sq2(aa, bb) }) } } // 补充定义保持不变 #[derive(Copy, Clone)] struct Square { pos: u32, piece: u32 } struct BitboardPD { path: u32, dest: u32 } struct Bs; struct Waypoint; impl Waypoint { fn a_square(a: Square) -> Vec<BitboardPD> { vec![] } }
额外说明
- 如果需要
Sq2的两个参数类型严格一致,可以使用Box<dyn Iterator<Item = Square>>做类型擦除,但会带来轻微性能开销。 - 若要让
SqIterator完全无缝适配标准库迭代器方法,可以为它实现Filter、Map等适配器的直接调用方法,或者直接在每次调用标准库适配器后手动包装回SqIterator。
内容的提问来源于stack exchange,提问作者eguneys
相关产品推荐
相关产品推荐

