I want to implement HasChildren
for all types which implement Element
and for all functions which return impl Element
.
My case use is that I have a Vec<Box<dyn HasChildren>>
in which I want to be able to store both types which implement Element
and functions which return impl Element
.
Worth noting that my wider use case requires using trait objects, so a solution eg using enums is not possible.
trait Element {}
trait HasChildren {}
impl<T: 'static + Element + Clone> HasChildren for T {}
// conflicting implementation
impl<F, E: Element> HasChildren for F where F: FnMut() -> E {}
// Types which I would like to use as HasChildren trait objects
#[derive(Clone)]
struct Foo {}
impl Element for Foo {}
fn get_element() -> impl Element {
Foo {}
}
// My use case - storing both the above types in a Vector
fn main() {
let mut data: Vec<Box<dyn HasChildren>> = Vec::new();
data.push(Box::new(Foo {}));
data.push(Box::new(get_element));
}
You could use the newtype pattern:
use std::ops::{Deref, DerefMut};
trait Element {}
trait HasChildren {}
// Newtype wrapper for `FnMut() -> E`
struct ElementFn<F: FnMut() -> E, E: Element>(F);
impl<F: FnMut() -> E, E: Element> Deref for ElementFn<F, E> {
type Target = F;
fn deref(&self) -> &F {
&self.0
}
}
impl<F: FnMut() -> E, E: Element> DerefMut for ElementFn<F, E> {
fn deref_mut(&mut self) -> &mut F {
&mut self.0
}
}
// conflicting implementation
impl<T: Element + Clone> HasChildren for T {}
impl<F: FnMut() -> E, E: Element> HasChildren for ElementFn<F, E> {}
// Types which I would like to use as HasChildren trait objects
#[derive(Clone)]
struct Foo {}
impl Element for Foo {}
fn get_element() -> impl Element {
Foo {}
}
// My use case - storing both the above types in a Vector
fn main() {
let mut data: Vec<Box<dyn HasChildren>> = Vec::new();
data.push(Box::new(Foo {}));
data.push(Box::new(ElementFn(get_element)));
}