Rust中修改boxed函数并重新赋值:为何要求T'static?能否规避?
Rust中Box<dyn Fn(T)>生命周期约束问题解析
先看你给出的代码:
struct S<T> { f: Box<dyn Fn(T)>, } impl<T> S<T> { fn test(mut self) { let f = self.f; let f = Box::new(move |t| f(t)); self.f = f; } }
为什么编译器要求添加T:'static约束?
问题出在trait对象的默认生命周期规则上:
- 当创建
Box<dyn Fn(T)这类未显式标注生命周期的trait对象时,Rust编译器会默认给它加上'static约束,实际类型等价于Box<dyn Fn(T) + 'static>。 - 你的闭包捕获了原有的
self.f,并被包装成新的Box<dyn Fn(T)>。如果T不是'static类型(比如T是带短生命周期的引用&'a i32),原有Fn(T)的逻辑可能依赖T的生命周期,此时新闭包要满足Fn(T) + 'static的约束,就必须要求T本身是'static的——否则T的生命周期无法覆盖'static,编译器就会抛出生命周期不足的错误。
能否不添加'static约束实现需求?
可以,只需要显式标注生命周期,明确trait对象的生命周期与T的关系即可:
struct S<'a, T: 'a> { f: Box<dyn Fn(T) + 'a>, } impl<'a, T: 'a> S<'a, T> { fn test(mut self) { let f = self.f; let f: Box<dyn Fn(T) + 'a> = Box::new(move |t| f(t)); self.f = f; } }
这里给结构体添加了生命周期参数'a,并指定T的生命周期至少不短于'a(T: 'a),同时把f的类型明确为Box<dyn Fn(T) + 'a>。新创建的闭包包装的trait对象会沿用指定的'a生命周期,而非默认的'static,也就不需要强制T是'static类型了。
内容的提问来源于stack exchange,提问作者DiscreteTom
相关产品推荐
相关产品推荐

