简体   繁体   中英

Function that accepts both &Vec<T> and &Vec<&T> in Rust

In my struct I have a from function that takes a shared reference to a vector of elements of type T and does some initialisation.

fn from(t: &Vec<T>) -> () {
    // ...
    for a in t {
        // ...
    }
    for a in t {
        // ...
    }
}

I also have another function from_partial that first performs some filtering on &Vec<T> and wants to pass this reduced list of elements to from . I don't want to clone so from_partial constructs the vector as Vec<&T> instead of Vec<T> . I also don't want to duplicate the logic in from as all in needs to do is loop over the vector and get a &T to store somewhere.

In my concrete type example, I can assign both &Vec<&Bar> and &Vec<Bar> to from

let a: &Vec<&Bar> = &test.iter().collect();
let b: &Vec<Bar> = test;
Foo::from(a); // can assign &Vec<&Bar>
Foo::from(b); // can assign &Vec<Bar>

However when working with generic types, I am unable to do so:

fn from_partial(t: &Vec<T>) -> () {
    // Here a function is called that does some filtering on &Vec<T>
    // and returns &Vec<&T>, but omitting for brevity.
    let example: &Vec<&T> = &t.iter().collect();
    Self::from(example); // cannot assign &Vec<&T> to &Vec<T>?
}

Here's the MVCE ( Playground ):

struct Foo<T> {
    t: T,
}
struct Bar {}

impl<T> Foo<T> {
    fn from(t: &Vec<T>) -> () {
        let mut v = Vec::new();
        for a in t {
            // ...
            v.push(Foo { t: a })
        }
        for a in t {
            // ...
            v.get(0);
        }
    }

    fn from_partial(t: &Vec<T>) -> () {
        // Here a function is called that does some filtering on &Vec<T>
        // and returns &Vec<&T>, but omitting for brevity.
        let example: &Vec<&T> = &t.iter().collect();
        Self::from(example); // cannot assign &Vec<&T> to &Vec<T>?
    }
}

fn main() {}

fn test(test: &Vec<Bar>) {
    let a: &Vec<&Bar> = &test.iter().collect();
    let b: &Vec<Bar> = test;
    Foo::from(a); // can assign &Vec<&Bar>
    Foo::from(b); // can assign &Vec<Bar>
}

Is there any sort of constraint I can add on T that would make this possible? To essentially prevent me from duplicating exactly the same logic in from twice.

You need to replace Self::from(example); with Foo::from(example); .

Consider that T is Bar , then your from_partial call takes &Vec<Bar> . The issue is that Self then represents Foo::<Bar> , but you're trying to call from with &Bar , ie you need Foo::<&Bar> .

fn from_partial(t: &Vec<T>) -> () {
    let example: &Vec<&T> = &t.iter().collect();
    Foo::from(example);
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM