Rust中为实现len()方法的类型编写通用长度比较泛型函数
通用
longer函数实现方案 Rust标准库没有提供覆盖所有带.len()方法类型的内置trait,因此我们可以通过自定义长度特征的方式实现通用逻辑,具体实现如下:
完整可运行代码
// 定义长度特征,用于标记所有支持获取长度的类型 trait HasLength { fn len(&self) -> usize; } // 给常用的带len()方法的类型实现该特征 impl<T> HasLength for Vec<T> { fn len(&self) -> usize { self.len() } } impl HasLength for String { fn len(&self) -> usize { self.len() } } // 支持字符串切片/字面量 impl HasLength for str { fn len(&self) -> usize { self.len() } } // 支持数组切片 impl<T> HasLength for [T] { fn len(&self) -> usize { self.len() } } /// 比较两个带长度属性的实例,返回长度更长的对象引用 fn longer<'a, T: HasLength + ?Sized>(x: &'a T, y: &'a T) -> &'a T { if x.len() > y.len() { x } else { y } } fn main() { let vec1 = vec![1, 2, 3]; let vec2 = vec![1, 2, 3, 4]; println!("Longer vector is: {:?}", longer(&vec1, &vec2)); let string1 = String::from("abcd"); let string2 = String::from("xyz"); println!("Longest string is : {:?}", longer(&string1, &string2)); }
关键说明
- 自定义
HasLengthtrait的原因:内置的ExactSizeIterator仅支持迭代器类型,无法兼容Vec、String等非迭代器的集合类型,自定义特征可以灵活匹配所有需要支持的类型。 - 泛型约束中添加
?Sized是为了兼容动态大小类型(DST),比如str、[T]这类编译期无法确定大小的类型,让函数同时支持&String、&Vec<T>这类常规引用和&str、&[T]这类切片引用。 - 如果需要支持更多带
len()方法的类型(比如HashMap、HashSet、VecDeque等),只需要给对应类型实现HasLengthtrait即可,实现仅需调用类型自带的len()方法,无额外运行时开销。 - 可以用宏简化重复的特征实现代码,避免给每个类型手动写相同逻辑的impl:
macro_rules! impl_has_len { ($($t:ident),+ $(,)?) => { $( impl<T> HasLength for $t<T> { fn len(&self) -> usize { self.len() } } )+ }; } // 批量给其他单泛型参数集合类型实现特征 impl_has_len!(std::collections::HashSet, std::collections::VecDeque, std::collections::BinaryHeap);
内容的提问来源于stack exchange,提问作者Miokloń
相关产品推荐
相关产品推荐

