-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathgeneric_dyn_dispatch.rs
96 lines (78 loc) · 1.85 KB
/
generic_dyn_dispatch.rs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
#![allow(unused)]
// Static and dynamic dispatch
// Static dispatch
// - function to call is known at compile time
// - monomorphization (code size can be larger)
// - no run time cost (no vtable lookup)
// Dynamic dispatch
// - function to call is known at run time
// - vtable lookup (code size is smaller)
// - run time overhead (vtable lookup)
// Trait object
// Value that implements a trait, but its concrete type is unknown at compile time
#[derive(Debug)]
struct A;
#[derive(Debug)]
struct B;
trait F {
fn f(&self);
}
impl F for A {
fn f(&self) {
println!("{:?}", self)
}
}
impl F for B {
fn f(&self) {
println!("{:?}", self)
}
}
// Static dispatch
// T must resolve to a concrete type at compile time
fn static_dispatch<T: F>(t: &T) {
t.f();
}
// Dynamic dispatch
// t is known at run time
// &dyn F is a reference to a trait object
// dyn - used to create a trait object
// Why &?
// - pointer to a type that implements F
// - trait obj (dyn F) is unsized
fn dyn_dispatch(t: &dyn F) {
t.f();
}
// Difference between &dyn F and Box<dyn F>
// &dyn F - borrow
// Box<dyn F> takes ownership
fn dyn_dispatch_box(t: Box<dyn F>) {
t.f();
}
fn main() {
let obj = A;
static_dispatch(&obj);
let obj = B;
static_dispatch(&obj);
// user input
let input = "A";
let obj: &dyn F = match input {
"A" => &A,
"B" => &B,
_ => panic!(),
};
// This won't compile
// Type must be known at compile time
// static_dispatch(obj);
dyn_dispatch(obj);
// Box<dyn T>
// Allocates memory on the heap, stores concrete instance
let obj: Box<dyn F> = match input {
"A" => Box::new(A),
"B" => Box::new(B),
_ => panic!(),
};
dyn_dispatch_box(obj);
// This won't compile
// dyn_dispatch_box takes ownership
// let x = obj;
}