Rust中如何将Box<dyn Fn>用作&impl Fn?
问题解决:闭包传递给外部crate的
&impl Fn参数报错 错误原因
你传递的&*retv.injection_closure是指向**动态大小类型(DST)的引用,具体为&dyn Fn(&f64) -> f64。外部函数LibObj::new的参数&impl Fn(&Arg) -> Arg默认要求被引用类型必须是编译期大小可知(Sized)**的,而动态大小类型不满足该约束,因此触发编译错误。
解决方案
直接传递Box本身的引用(&retv.injection_closure),而非解引用Box后的动态类型引用。Box<dyn Fn(...)>是大小固定的类型(Sized),且它通过Deref trait自动解引用到内部闭包,完全满足Fn(&f64) -> f64的 trait 约束,符合外部函数的要求。
修改后的完整代码
use std::rc::Rc; use std::cell::Cell; /// 我可控制的代码 struct MyWrapper<'a> { obj: Option<LibObj<'a, f64>>, injection_closure: Box<dyn Fn(&f64) -> f64 + 'a>, } impl<'a> MyWrapper<'a> { fn new(transaction: Rc<Cell<f64>>) -> MyWrapper<'a> { let injection_closure = Box::new(move |_: &f64| transaction.get()); let mut retv = MyWrapper { injection_closure, obj: None, }; // 直接传递Box的引用,而非解引用后的dyn trait引用 retv.obj = Some(LibObj::new(&retv.injection_closure)); retv } } /// 我无法控制的外部代码 struct LibObj<'f_lifetime, Arg> { my_thing: ThingWrapper<'f_lifetime, Arg>, } impl<'f_lifetime, Arg> LibObj<'f_lifetime, Arg> { pub fn new(f: &'f_lifetime impl Fn(&Arg) -> Arg) -> Self { let thing = ThingWrapper::new(f); LibObj { my_thing: thing } } } pub struct ThingWrapper<'f_lifetime, Arg> { f: &'f_lifetime dyn Fn(&Arg) -> Arg, } impl<'f_lifetime, Arg> ThingWrapper<'f_lifetime, Arg> { pub fn new(f: &'f_lifetime impl Fn(&Arg) -> Arg) -> Self { ThingWrapper { f } } }
补充说明
如果需要对闭包进行多所有权管理,也可以用Rc替代Box,修改方式完全一致——只需将Box替换为Rc,传递&retv.injection_closure即可。
内容的提问来源于stack exchange,提问作者deftfyodor
相关产品推荐
相关产品推荐

