gpt4 book ai didi

callback - 无法从回调向量调用函数,获取 `expected function, found ` Box`

转载 作者:行者123 更新时间:2023-11-29 08:14:26 26 4
gpt4 key购买 nike

我正在尝试在 Rust 1.11 中实现回调系统。我想我已经正确设置了系统来存储回调,但我在实际调用它们时遇到了麻烦。示例代码:

struct Container<'a, T> {
callbacks: Vec<Box<FnMut(T) + 'a>>,
}

impl<'a, T: Copy + PartialEq> Container<'a, T> {
fn new() -> Self {
Container {
callbacks: Vec::new(),
}
}

fn add_callback<F: 'a + FnMut(T)>(&mut self, callback: F) -> usize {
let cb_id = self.callbacks.len();
self.callbacks.push(Box::new(callback));
cb_id
}

fn call_by_id(&self, cb_id: usize, value: T) {
// This doesn't work and I don't know why:
self.callbacks[cb_id](value);

// It still doesn't work (same error) when I try to dereference the Box
// *self.callbacks[cb_id](value);

// It's not a dereferencing scoping issue, either
// *(self.callbacks[cb_id])(value);
}

}

fn main() {
let mut list = Vec::new();

{
let mut container = Container::new();
let append = container.add_callback(|v| list.push(v));

container.call_by_id(append, 3);
container.call_by_id(append, 4);
}

println!("List contains: {:?}", list);
// Expect "List contains: [3, 4]", but it doesn't compile
}

( Playground link )

这会产生以下错误:

error: expected function, found `Box<std::ops::FnMut(T) + 'a>`
--> <anon>:20:9
|>
20 |> self.callbacks[cb_id](value);
|> ^^^^^^^^^^^^^^^^^^^^^^^^^^^^

error: aborting due to previous error

这对于 Rust 来说是非常无益的;我很难通过 Google 或在此处搜索找到此错误的其他实例。

Box文档声称有一个通用的 impl<T> Deref for Box<T> where T: ?Sized , 和 Sized文档说语法 ?Sized用于删除 Sized 的要求特征。我理解这意味着,一起,Box工具 Deref对于每个 T , 尺寸与否,所以它应该在这里发挥作用。

如果是这样的话,我完全不明白为什么我不能只调用 Box包含回调,或(最坏情况)取消引用 self.callbacks[cb_id]访问可调用对象。目前我最好的猜测是它与游戏中的生命周期有关,但如果是这样,我只是不知道如何调整它们以使其发挥作用。

最佳答案

这是一个较小的复制品:

fn main() {
let a: Vec<Box<FnMut()>> = vec![Box::new(|| println!("called"))];
a[0]();
}

让我们分解它并观察类型和错误:

fn call_by_id(&self, cb_id: usize, value: T) {
let () = self.callbacks[cb_id];
}

这表明类型是Box<std::ops::FnMut(T)> .到目前为止,一切都很好。将其存储在变量中并继续:

fn call_by_id(&self, cb_id: usize, value: T) {
let x = self.callbacks[cb_id];
x(value);
}

啊,对了:error: cannot borrow immutable `Box` content `*x` as mutable ...

fn call_by_id(&self, cb_id: usize, value: T) {
let mut x = self.callbacks[cb_id];
x(value);
}

糟糕:error: cannot move out of indexed content ...

fn call_by_id(&self, cb_id: usize, value: T) {
let mut x = &mut self.callbacks[cb_id];
x(value);
}

啊哈:error: cannot borrow immutable field `self.callbacks` as mutable ...

fn call_by_id(&mut self, cb_id: usize, value: T) {
let mut x = &mut self.callbacks[cb_id];
x(value);
}

编译成功! 我可能会把它留在这里(为 x 取一个更好的名字),但让我们看看是否可以将它恢复到一行。直接替换:

fn call_by_id(&mut self, cb_id: usize, value: T) {
(&mut self.callbacks[cb_id])(value);
}

不,回到error: expected function, found `&mut Box<std::ops::FnMut(T) + 'a>`也许是取消引用:

fn call_by_id(&mut self, cb_id: usize, value: T) {
(*self.callbacks[cb_id])(value);
}

不,error: cannot borrow immutable盒子content as mutable .更具体地说明可变性:

fn call_by_id(&mut self, cb_id: usize, value: T) {
(*&mut self.callbacks[cb_id])(value);
}

这行得通,但我不确定它是否优雅。


总而言之,问题在于回调的变量是不可变的。这是由两件事造成的:

  1. 回调向量的绑定(bind)不是可变的(通过 &self )。
  2. 回调的取消引用似乎 不理解可变性要求,除非您是明确的。我不是 100% 确定这是为什么。

请注意,在您的注释代码中:

*self.callbacks[cb_id](value);
*(self.callbacks[cb_id])(value);

我很确定它们是一样的; *的优先级会将其绑定(bind)到整个值的结果。我想你的意思是:

(*self.callbacks[cb_id])(value);

关于callback - 无法从回调向量调用函数,获取 `expected function, found ` Box<std::ops::FnMut(T) + 'a>`,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/39531899/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com