如何编写Rust中map返回迭代器的完整类型签名(含映射函数具体类型)
类型填写方法说明
首先纠正你对std::iter::Map泛型参数的认知偏差:Rust标准库中std::iter::Map仅包含2个泛型参数,分别是:
- 第一个参数:原迭代器类型
I,对应你给出的std::slice::Iter<'a, usize> - 第二个参数:映射函数类型
F,就是你要填的下划线位置
而bool是Map的迭代器Item关联类型的取值,由F的输出类型推导,不需要写在泛型参数列表里。
普通函数对应的类型填写逻辑
Rust中每个普通函数默认对应一个独一无二、无法手动书写的零大小函数项类型,如果你需要显式标注类型,需要先将函数强制转换为函数指针类型,操作示例如下:
// 先修正原函数的参数类型:numbers.iter()产出的元素是&usize,和原函数参数usize类型不匹配 fn is_big(a: &usize) -> bool { *a > 7 } let numbers: Vec<usize> = vec![1,2,3]; // 强转函数为指针类型后,即可写出完整的mappeds类型 let mappeds: std::iter::Map<std::slice::Iter<'_, usize>, fn(&usize) -> bool> = numbers.iter().map(is_big as fn(&usize) -> bool);
你要填的下划线位置的类型就是fn(&usize) -> bool,根据你实际函数的签名调整参数和返回值类型即可。
对应trait实现场景的两种方案
方案1:Rust 1.75+ 推荐用关联类型impl Trait
不需要手动写复杂的Map类型,直接用impl Iterator声明关联类型即可,无额外运行时开销:
trait MyTrait<V> { type Iter<'a>: Iterator<Item = &'a V> where Self: 'a, V: 'a; fn iter<'a>(&'a self) -> Self::Iter<'a>; } impl<V> MyTrait<V> for Vec<V> { // 直接用impl Trait,编译器自动推导具体类型 type Iter<'a> = impl Iterator<Item = &'a V> where Self: 'a, V: 'a; fn iter<'a>(&'a self) -> Self::Iter<'a> { // 此处填写你自己的map逻辑即可 self.iter().map(|x| x) } }
方案2:低版本Rust用函数指针
如果你需要兼容旧版本Rust,可以用函数指针类型,缺点是会带来极小的动态调用开销:
trait MyTrait<V> { type Iter<'a>: Iterator<Item = &'a V> where Self: 'a, V: 'a; fn iter<'a>(&'a self) -> Self::Iter<'a>; } impl<V> MyTrait<V> for Vec<V> where V: 'static { type Iter<'a> = std::iter::Map<std::slice::Iter<'a, V>, fn(&'a V) -> &'a V> where Self: 'a, V: 'a; fn iter<'a>(&'a self) -> Self::Iter<'a> { // 定义你的映射函数,强转为函数指针 fn map_fn<T>(x: &T) -> &T { x } self.iter().map(map_fn as fn(&'a V) -> &'a V) } }
内容的提问来源于stack exchange,提问作者mako
相关产品推荐
相关产品推荐

