Skip to content

Instantly share code, notes, and snippets.

@alexxbb
Created January 11, 2022 22:56
Show Gist options
  • Save alexxbb/971f999a96253778fff710d97d79a8bf to your computer and use it in GitHub Desktop.
Save alexxbb/971f999a96253778fff710d97d79a8bf to your computer and use it in GitHub Desktop.
Downcast trait object to generic concrete type
#![allow(unused)]
use std::any::Any;
use std::marker::PhantomData;
struct NumericAttr<T> {
_m: PhantomData<T>,
}
impl<T> NumericAttr<T> {
fn get(&self){}
fn set(&self){}
}
trait AttribTypeImpl {
type Type;
// Impl type specific stuf
}
trait AnyAttribWrapper {
fn as_any(&self) -> &dyn Any;
}
impl<T> AttribTypeImpl for NumericAttr<T> {
type Type = T;
}
impl<T: Any + AttribTypeImpl> AnyAttribWrapper for T {
fn as_any(&self) -> &dyn Any {
self
}
}
struct Attribute(Box<dyn AnyAttribWrapper>);
impl Attribute {
fn new(inner: Box<dyn AnyAttribWrapper>) -> Self {
Attribute(inner)
}
fn downcast<T: AttribTypeImpl + 'static>(&self) -> Option<&T> {
self.0.as_any().downcast_ref::<T>()
}
}
fn get_attributes() -> Vec<Attribute> {
let a = NumericAttr::<f32> { _m: PhantomData };
let b = NumericAttr::<i32> { _m: PhantomData };
let c = NumericAttr::<u8> { _m: PhantomData };
vec![
Attribute::new(Box::new(a)),
Attribute::new(Box::new(b)),
Attribute::new(Box::new(c)),
]
}
fn main() {
for attr in &get_attributes() {
if let Some(a) = attr.downcast::<NumericAttr<i32>>() {
a.get();
a.set();
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment