Reputation: 15266
I have a trait that I own:
trait Reducer {
fn reduce(&self) -> Res;
}
I want to implement for the following cases:
struct MyStruct {... fields ...}
impl Reducer for Vec<MyStruct> {
fn reduce(&self) -> Res { ... some implementation ... }
}
I want to get for as cheap as possible (not duplicating code etc.) for the refs of objects in Vec:
for instance:
// I want this please:
impl Reducer for Vec<&MyStruct> {
// it's the same implementation as before
}
How should I change my impl
signature to satisfy both cases?
Upvotes: 1
Views: 64
Reputation: 6651
Using the Borrow
trait you can generalize for all types that can be borrowed as a &MyStruct
(which in particular includes MyStruct
and &MyStruct
):
use std::borrow::Borrow;
trait Reducer {
fn reduce(&self) -> Res;
}
struct MyStruct;
struct Res;
impl<T: Borrow<MyStruct>> Reducer for Vec<T> {
fn reduce(&self) -> Res {
for t in self {
let _t: &MyStruct = t.borrow();
// do something with `_t`
}
Res
}
}
fn main() {
let v: Vec<MyStruct> = vec![];
let v_ref: Vec<&MyStruct> = vec![];
// fully qualified because it gets mangled with `Iterator::reduce` otherwise.
Reducer::reduce(&v);
Reducer::reduce(&v_ref);
}
Upvotes: 2
Reputation: 155046
If your reducer only needs to iterate over the items in the Vec
, then there is no difference between Vec<T>
and Vec<&T>
because both can easily produce an iterator over &T
. For example:
// actual implementation
fn reduce_it<'a>(_items: impl Iterator<Item = &'a MyStruct>) -> Res {
todo!()
}
impl Reducer for Vec<MyStruct> {
fn reduce(&self) -> Res {
reduce_it(self.iter())
}
}
impl Reducer for Vec<&MyStruct> {
fn reduce(&self) -> Res {
reduce_it(self.iter().copied())
}
}
Upvotes: 1