如何为返回`impl Trait`的Rust函数实现扩展Trait模式?
方案1:动态分发实现(全编译器版本兼容)
这是最简单的兼容方案,将返回的迭代器装箱为特征对象,仅会产生极小的运行时开销,绝大多数场景下可以忽略:
trait IntoIteratorMathExt where Self: IntoIterator, { fn add<I>(self, other: I) -> Box<dyn Iterator<Item = Self::Item>> where I: IntoIterator<Item = Self::Item> + 'static, Self: 'static, Self::Item: std::ops::Add<Output = Self::Item> + 'static; } impl<T: IntoIterator> IntoIteratorMathExt for T { fn add<I>(self, other: I) -> Box<dyn Iterator<Item = Self::Item>> where I: IntoIterator<Item = Self::Item> + 'static, Self: 'static, Self::Item: std::ops::Add<Output = Self::Item> + 'static, { Box::new(self.into_iter().zip(other).map(|(x, y)| x + y)) } } fn main() { let a = vec![1, 2, 3, 4, 5]; let b = (6..=10).map(|x| x + 1); let sum_iter = a.add(b); let sum_vec = sum_iter.collect::<Vec<i32>>(); assert_eq!(sum_vec, vec![8, 10, 12, 14, 16]); }
方案2:零开销静态分发(Rust 1.75+ 支持)
Rust 1.75版本已经稳定支持**Trait方法返回impl Trait(RPITIT)**特性,你原来的写法仅需修正笔误即可正常编译运行,完全零开销:
trait IntoIteratorMathExt where Self: IntoIterator, { fn add<I>(self, other: I) -> impl Iterator<Item = Self::Item> where I: IntoIterator<Item = Self::Item>, Self::Item: std::ops::Add<Output = Self::Item>; } impl<T: IntoIterator> IntoIteratorMathExt for T { fn add<I>(self, other: I) -> impl Iterator<Item = Self::Item> where I: IntoIterator<Item = Self::Item>, Self::Item: std::ops::Add<Output = Self::Item>, { self.into_iter().zip(other).map(|(x, y)| x + y) } } fn main() { let a = vec![1, 2, 3, 4, 5]; let b = (6..=10).map(|x| x + 1); let sum_iter = a.add(b); let sum_vec = sum_iter.collect::<Vec<i32>>(); assert_eq!(sum_vec, vec![8, 10, 12, 14, 16]); }
注:你原有代码的唯一笔误是定义的Trait名为IntoIteratorMathExt,实现时错误写成了IteratorMathExt,修正后即可在1.75及以上版本编译器正常运行。
方案3:手动实现迭代器包装器(旧版本零开销方案)
如果需要兼容1.75以下的编译器版本又不想承担动态分发开销,可以手动定义迭代器包装类型,手动实现Iterator特征,实现起来相对繁琐,仅在性能敏感且需要兼容旧版本的场景下使用。
内容的提问来源于stack exchange,提问作者sausageberg
相关产品推荐
相关产品推荐

