Rust中兼容自有和引用型可迭代对象的惯用方法
解决方案:借助
Borrow trait实现通用的求和函数 要让foo同时支持&i32和i32类型的迭代器,可以通过std::borrow::Borrow trait来抽象这两种类型的共性——它们都能提供一个&i32的引用。
修改后的foo函数
use std::borrow::Borrow; fn foo<I>(it: I) -> i32 where I: IntoIterator, I::Item: Borrow<i32>, { it.into_iter().map(|item| *item.borrow()).sum() }
原理说明
- 对于
&i32类型:Borrow<i32>会直接返回自身,解引用后就是原始的i32值; - 对于
i32类型:Borrow<i32>会返回&self,解引用后同样得到i32值。
这样无论传入的是&Vec<i32>(其迭代器Item为&i32),还是转换后的迭代器(Item为i32),都能被foo正确处理。
完整可运行代码
use std::borrow::Borrow; fn main() { let v: Vec<i32> = vec![1, 2, 3]; // 原调用正常工作 println!("{}", foo(&v)); let vs: Vec<&str> = vec!["1", "2", "3"]; let converting_iterator = vs.iter().map(|s| s.parse::<i32>().unwrap()); // 现在这个调用也能正常运行 println!("{}", foo(converting_iterator)); } fn foo<I>(it: I) -> i32 where I: IntoIterator, I::Item: Borrow<i32>, { it.into_iter().map(|item| *item.borrow()).sum() }
替代方案:使用AsRef trait
也可以用AsRef<i32>替代Borrow<i32>,两者效果几乎一致,修改后的约束和实现如下:
use std::convert::AsRef; fn foo<I>(it: I) -> i32 where I: IntoIterator, I::Item: AsRef<i32>, { it.into_iter().map(|item| *item.as_ref()).sum() }
内容的提问来源于stack exchange,提问作者cadolphs
相关产品推荐
相关产品推荐

