Suppose, I have a number of traits:
trait Device {}
trait Named {}
trait Report {}
I have a number of structs, some of which implement some subset of these traits, and then I have some logic that expects a type that implements all of them, say, I want to have a collection of devices that have names and can produce reports. To reduce the typing (on the keyboard), I create a combined trait:
pub trait ReportNamedDevice: Named + Device {}
impl<T: Named + Device> ReportNamedDevice for T {}
(Report
is omitted for now until I can make the existing ones work)
And then I use a collection of those in a struct:
pub struct Room<'a> {
pub name: String,
pub devices: Vec<&'a dyn ReportNamedDevice>,
}
Now, the room itself is Named
, and I want to be able to add it to a House
. And I want all of my collections of Named
things to contain things with unique names, so I write the following filter function:
fn name_is_in_named_vector(name: &String, haystack: &Vec<&dyn Named>) -> bool {
haystack
.iter()
.map(|x| x.name().clone())
.collect::<Vec<String>>()
.contains(name)
}
But when I try to use it in my Room
impl, I get a mismatched types
error, because the compiler doesn't treat ReportNamedDevice
as Named
:
impl<'a> Room<'a> {
pub fn add_device(&mut self, device: &'a dyn ReportNamedDevice) {
if !name_is_in_named_vector(device.name(), &self.devices) {
self.devices.push(device)
}
}
}
I know I could replace the haystack
type in the filter function, but I would like to be able to reuse it for filtering rooms as well.
Is there a way I can make this work?