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, i.e. you need Foo::<&Bar>.
fn from_partial(t: &Vec<T>) -> () {
let example: &Vec<&T> = &t.iter().collect();
Foo::from(example);
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With