我正在使用盒装闭包在结构上使用回调。但是,我还不知道如何从另一个调用一个闭包:
struct MyStruct {
first: Box<Fn()>,
second: Box<Fn()>,
}
impl MyStruct {
fn method(&mut self) {
self.second = Box::new(|| {
// How can I make this work?
(self.first)();
});
}
}
fn main() {
let _ = MyStruct {
first: Box::new(|| {}),
second: Box::new(|| {}),
};
}
这给出了:
error[E0495]: cannot infer an appropriate lifetime due to conflicting requirements
--> src/main.rs:8:32
|
8 | self.second = Box::new(|| {
| ________________________________^
9 | | // How can I make this work?
10 | | (self.first)();
11 | | });
| |_________^
|
note: first, the lifetime cannot outlive the anonymous lifetime #1 defined on the method body at 7:5...
--> src/main.rs:7:5
|
7 | / fn method(&mut self) {
8 | | self.second = Box::new(|| {
9 | | // How can I make this work?
10 | | (self.first)();
11 | | });
12 | | }
| |_____^
= note: ...so that the types are compatible:
expected &&mut MyStruct
found &&mut MyStruct
= note: but, the lifetime must be valid for the static lifetime...
= note: ...so that the expression is assignable:
expected std::boxed::Box<(dyn std::ops::Fn() + 'static)>
found std::boxed::Box<dyn std::ops::Fn()>
在这种情况下,我不太确定这是什么意思。
我知道借用规则是导致错误的原因,但是Rust中是否有任何合法方法能够获得与我要执行的操作相同的效果?
我不确定仅凭此是否有意义,为什么我要这样做。这是最小的复制品。我可以提供一个更大的例子,但是涉及的更多。
答案 0 :(得分:1)
这是您的问题的部分解决方案:请勿使用Box<Fn()>
,而应使用Box<Fn(&MyStruct)>
,即将“ self
”显式传递给闭包。
但是,据我所知,这仅允许闭包采用&MyStruct
(与&mut MyStruct
相对),即闭包无法修改给定的MyStruct
(这可能会或可能不足以满足您的用例。
struct MyStruct {
first: Box<Fn(&MyStruct)>,
second: Box<Fn(&MyStruct)>,
}
impl MyStruct {
fn method(&mut self) {
self.second = Box::new(|self2: &MyStruct| {
(self2.first)(self2)
});
}
}
fn main() {
let _ = MyStruct {
first: Box::new(|_self_ignored| {}),
second: Box::new(|_self_ignored| {}),
};
}
如果闭包应该修改MyStruct
,则会遇到(self2.first)(self2)
的问题,因为这将借用self2
两次,一次是可变的。您可以通过暂时替换first
/ second
来解决此问题,但是这样,每次调用first
/ second
时都需要格外小心,因为它随时可能无法调用first
/ second
。
可能有unsafe
种方法可以解决此问题。就是说,我想(或者至少希望如此)有一种更好的方法来实现您要实现的目标。