トレイトオブジェクトの保持とライフタイム
トレイトオブジェクトとライフタイム
トレイトオブジェクトを保持する場合は、ライフタイムが必要となる時がある。
- ジェネリクス型パラメーター
- 参照型
トレイトオブジェクト x ジェンリクス型パラメーター
struct Zoo { animals: Vec<Box<dyn Animal>>, // trait Animal { .. } impl Zoo { // 型パラメーターを用いる fn insert<A>(&mut self, animal: A) where A: Animal { self.animals.push(Box::new(animal)); } } /* error[E0310]: the parameter type `A` may not live long enough | 17 | fn insert<A>(&mut self, animal: A) | - help: consider adding an explicit lifetime bound...: `A: 'static` ... 21 | self.animals.push(Box::new(animal)); | ^^^^^^^^^^^^^^^^ ...so that the type `A` will meet its required lifetime bounds */
ライフタイムを付与する。
struct Zoo<'a> { animals: Vec<Box<dyn Animal + 'a>>, } impl<'a> Zoo<'a> { fn insert<A>(&mut self, animal: A) where A: Animal + 'a { self.animals.push(Box::new(animal)); } }
トレイトオブジェクト x 参照型
トレイトオブジェクトに参照型を指定する場合は、ライフタイムを付ける必要がある。
impl<'a> Quack for &'a bool {} struct MasterQuack { q: Box<dyn Quack>, // trait Quack .. } let a = true; MasterQuack {q: Box::new(&a)}; /* error[E0597]: `a` does not live long enough | 19 | MasterQuack {q: Box::new(&a)}; | ---------^^- | | | | | borrowed value does not live long enough | cast requires that `a` is borrowed for `'static` 20 | } | - `a` dropped here while still borrowed */
ライフタイムを付与する
struct MasterQuack<'a> { q: Box<dyn Quack + 'a>, }
トレイトオブジェクト x クロージャー
pub struct MessageHandler<T: Hash + Eq, U> { handlers: HashMap<T, Vec<Box<dyn Fn(&U)>>>, } impl<T, U>MessageHandler<T, U> where T: Hash + Eq, { pub fn on<F>(&mut self, event: T, listener: F) where F: Fn(&U), { let listeners = self.handlers.entry(event).or_insert(vec![]); listeners.push(Box::new(listener)); } error[E0310]: the parameter type `F` may not live long enough | 18 | pub fn on<F>(&mut self, event: T, listener: F) | - help: consider adding an explicit lifetime bound...: `F: 'static` ... 23 | listeners.push(Box::new(listener)); | ^^^^^^^^^^^^^^^^^^ ...so that the type `F` will meet its required lifetime bounds
トレイトオブジェクト x 具体型
具体型を指定する場合は、ライフタイムの指定は不要。
struct Zoo<'a> { animals: Vec<Box<dyn Animal + 'a>>, } impl<'a> Zoo<'a> { // ジェネリクス型パラメーターは、ライフタイムが必要 fn insert<A>(&mut self, animal: A) where A: Animal + 'a { self.animals.push(Box::new(animal)); } // 具体型は、ライフタイムが不要 fn insert(&mut self, monkey: Monkey) { self.animals.push(Box::new(monkey)); } }