Skip to content

Instantly share code, notes, and snippets.

@afilini
Created January 30, 2020 13:11
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save afilini/a1bd7eea70d659dcc9b78775cd778754 to your computer and use it in GitHub Desktop.
Save afilini/a1bd7eea70d659dcc9b78775cd778754 to your computer and use it in GitHub Desktop.
Runtime templates
#[derive(Debug)]
struct A {
val: u32,
}
#[derive(Debug)]
struct B {
val: String,
}
#[derive(Debug)]
enum Enum {
VarA(A),
VarB(B),
}
trait MyType: std::fmt::Debug {
fn print_val(&self);
fn print_val_with_arg(&mut self, arg: u32) -> u32;
fn default(&self) {
println!("default");
}
}
impl dyn MyType {
fn not_a_trait_method(&self) {
println!("not a trait method!");
dbg!(self);
}
}
impl MyType for A {
fn print_val(&self) {
dbg!(self);
}
fn print_val_with_arg(&mut self, arg: u32) -> u32 {
dbg!(self);
dbg!(arg);
arg
}
fn default(&self) {
println!("default override");
}
}
impl MyType for B {
fn print_val(&self) {
dbg!(self);
}
fn print_val_with_arg(&mut self, arg: u32) -> u32 {
dbg!(self);
dbg!(arg);
arg
}
}
macro_rules! impl_enum_method_body {
($name:ident, $self:ty, $ret:ty, $( $param:ident:$type:ty ),* ) => {
fn $name(self: $self, $( $param:$type, )*) -> $ret {
match self {
Enum::VarA(x) => x.$name($( $param, )*),
Enum::VarB(x) => x.$name($( $param, )*),
}
}
};
}
macro_rules! impl_enum_method {
($name:ident, $ret:ty, $( $param:ident:$type:ty ),* ) => {
impl_enum_method_body!($name, &Self, $ret, $( $param:$type ),* );
};
($name:ident, $( $param:ident:$type:ty ),* ) => {
impl_enum_method_body!($name, &Self, (), $( $param:$type ),* );
};
($name:ident) => {
impl_enum_method_body!($name, &Self, (), );
};
}
macro_rules! impl_mut_enum_method {
($name:ident, $ret:ty, $( $param:ident:$type:ty ),* ) => {
impl_enum_method_body!($name, &mut Self, $ret, $( $param:$type ),* );
};
($name:ident, $( $param:ident:$type:ty ),* ) => {
impl_enum_method_body!($name, &mut Self, (), $( $param:$type ),* );
};
($name:ident) => {
impl_enum_method_body!($name, &mut Self, (), );
};
}
impl MyType for Enum {
impl_enum_method!(print_val);
impl_mut_enum_method!(print_val_with_arg, u32, arg: u32);
impl_enum_method!(default);
}
fn main() {
let mut x = Enum::VarA(A { val: 42 });
x.print_val_with_arg(84);
x.default();
let x_t: Box<dyn MyType> = Box::new(x);
x_t.not_a_trait_method();
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment