我正在尝试编写一个处理整数序列的函数。
fn process_one(n: u32) {}
fn process<II>(ii: II)
where
II: IntoIterator<Item = u32>,
{
for n in ii {
process_one(n);
}
}
我希望客户端能够传递Vec<u32>
而不消费它(process(&v)
)。由于<&Vec<u32> as IntoIterator>::Item
为&u32
,因此无法使用此功能;我必须通过v.iter().cloned()
,这很烦人。
或者,我可以制作绑定Item = &u32
并使用process_one(*n)
,但后来我遇到相反的问题。
我正在试图想出一种编写这种通用的方法,但我无法弄清楚如何。据我所知,AsRef
,Borrow
,ToOwned
或Deref
都不起作用。
我需要的是一种写这个的方法:
fn process<II>(ii: II)
where
II: IntoIterator<Item = MAGIC>, /* MORE MAGIC */
{
for n in ii {
process_one(MAGIC(n));
}
}
以便所有这些编译:
fn test() {
let v: Vec<u32> = vec![1, 2, 3, 4];
process(&v);
process(v);
process(1..10);
}
我知道我可以使用自定义特征来做到这一点,但我觉得应该有一种没有所有样板的方法。
答案 0 :(得分:9)
Borrow
有效:
use std::borrow::Borrow;
fn main() {
let x = vec![1, 2, 3];
process(x.iter());
process(x);
process(1..3);
}
fn process_one(n: u32) {
println!("{}", n)
}
fn process<I>(iter: I)
where
I: IntoIterator,
I::Item: Borrow<u32>,
{
for x in iter {
process_one(*x.borrow());
}
}
答案 1 :(得分:2)
以下是我如何使用自定义特征进行操作。
trait ToValue<V> {
fn to_value(self) -> V;
}
impl<T> ToValue<T> for T {
fn to_value(self) -> T {
self
}
}
impl<'a, T> ToValue<T> for &'a T
where
T: Copy,
{
fn to_value(self) -> T {
*self
}
}
fn process<N, II>(ii: II)
where
II: IntoIterator<Item = N>,
N: ToValue<u32>,
{
for n in ii {
process_one(n.to_value());
}
}
虽然这解决了我的问题,但这让我感到非常不满意,而且我仍然认为应该有一个并不涉及我自己特质的解决方案。