Reputation: 619
I want to insert a value of type Box<T>
into a Vec<Box<Trait>>
and then get a reference to that value back. (T
is a generic type that implements Trait
). The returned value should be of type &T
The implementation below almost works, except there is no way to convert Box<Trait>
to Box<Any>
.
HashSet
has the (experimental) get_or_insert()
, which is perfect for this, but there seems to be no version for Vec
?
use std::any::Any;
trait A {}
struct B;
impl A for B {}
// How to write this function?
pub fn insert<'a, T>(vector: &mut Vec<Box<dyn A>>, value: T) -> &'a T where T: A {
// move the value into the vector
vector.push(Box::new(value));
// get the reference to the inserted value back
let it: &Box<dyn Any> = vector.last().unwrap(); // compile error
match it.downcast_ref::<T>() {
Some(i) => i,
None => panic!(),
}
}
fn main() {
let mut vec: Vec<Box<dyn A>> = Vec::new();
let b = B;
let b_ref = insert(&mut vec, b);
// can't use b here since moved, so need b_ref
}
Upvotes: 2
Views: 5006
Reputation: 4219
You can define a helper trait that is implemented for all types like this:
pub trait AToAny: 'static {
fn as_any(&self) -> &dyn Any;
}
impl<T: 'static> AToAny for T {
fn as_any(&self) -> &dyn Any {
self
}
}
Then require it to be implemented for subtypes of A.
pub trait A: AToAny {
}
You can now call .as_any()
on the &dyn A
you get from the vector.
pub fn insert<'a, T: A>(vector: &'a mut Vec<Box<dyn A>>, value: T) -> &'a T {
vector.push(Box::new(value));
let it: &dyn Any = vector.last().unwrap().as_any();
match it.downcast_ref::<T>() {
Some(i) => i,
None => panic!(),
}
}
Upvotes: 10