How to write a generic function taking any iterator of `u32` or `&u32`?

Deadly 提交于 2020-11-29 08:20:42

问题


I'm trying to write a function that processes a sequence of integers.

fn process_one(n: u32) {}

fn process<II>(ii: II)
where
    II: IntoIterator<Item = u32>,
{
    for n in ii {
        process_one(n);
    }
}

I want the client to be able to pass a Vec<u32> without consuming it (process(&v)). This function can't be used because <&Vec<u32> as IntoIterator>::Item is &u32; I'd have to pass v.iter().cloned() instead, which is annoying.

Alternatively, I could make the bound Item = &u32 and use process_one(*n), but then I have the reverse problem.

I'm trying to think of a way to write this generically, but I can't figure out how. As far as I can tell, none of AsRef, Borrow, ToOwned, or Deref work.

What I need is a way to write this:

fn process<II>(ii: II)
where
    II: IntoIterator<Item = MAGIC>, /* MORE MAGIC */
{
    for n in ii {
        process_one(MAGIC(n));
    }
}

so that all of these compile:

fn test() {
    let v: Vec<u32> = vec![1, 2, 3, 4];
    process(&v);
    process(v);
    process(1..10);
}

I know I can do this using a custom trait, but I feel like there should be a way without all that boilerplate.


回答1:


Borrow works:

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());
    }
}



回答2:


Here's how I would do it with a custom trait.

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());
    }
}

While this solves my problem, it leaves me rather unsatisfied, and I still think there should be a solution that doesn't involve my own trait.



来源:https://stackoverflow.com/questions/48317761/how-to-write-a-generic-function-taking-any-iterator-of-u32-or-u32

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!