如何在HashMap中存储方法指针并调用它们

时间:2017-09-03 20:47:12

标签: methods rust borrow-checker

我正在尝试编写一个chip8模拟器,借用检查器让我很难过。

想法是通过查找HashMap内的方法指针然后执行此方法指针来解码操作码,但我无法使可变方法指针正常工作:

struct Chip8 {
    opcode: u16,
    //... other fields
    jump_table: HashMap<u16, Box<fn(&mut Chip8)>>,
}

使用指针的功能:

fn execute_decoded(&mut self, key: u16) {
    let func = self.jump_table.get(&key);

    match func {
        Some(func) => func(self),
        None => {
            println!("invalid op: {}", self.opcode);
            sleep(Duration::from_millis(10000));
            return;
        }
    }();

    self.program_counter = self.program_counter + 2;
}

检查员抱怨:

 cannot borrow `*self` as mutable because `self.jump_table` is also borrowed as immutable
   --> main.rs:168:36
    |
165 |             let func = self.jump_table.get(&key);
    |                        --------------- immutable borrow occurs here
...
168 |                 Some(func) => func(self),
    |                                    ^^^^ mutable borrow occurs here
...
178 |     }
    |     - immutable borrow ends here

我不明白为什么会发生这种错误。

为什么self.jump_table.get(&key)会借用?基于execute_decoded的签名,我假设它适用于self的可变借用版本,并且不需要额外的借用。

2 个答案:

答案 0 :(得分:4)

没有理由Box HashMap中的HashMap函数指针,只引入不需要的间接。

already been mentioned一样,你正在借用函数指针。问题是,没有理由。您只需复制函数指针即可将其与use std::collections::HashMap; struct Chip8 { jump_table: HashMap<u16, fn(&mut Chip8)>, } impl Chip8 { fn execute_decoded(&mut self, key: u16) { let func = self.jump_table.get(&key).map(|x| *x); match func { Some(func) => func(self), None => { println!("invalid op"); } }; } } fn main() {}

取消关联
      private void videoSource_New( object sender, ref Bitmap image )

答案 1 :(得分:2)

Rust中的HashMap拥有其中的所有内容。为了得到你的函数指针,你要用let func = self.jump_table.get(&key);借用它。现在,func 无法借用 self.jump_tableself的元素)。

问题是您正试图将self全部传递到func。如果您以不可变的方式传递self,这样会很好,因为您可以根据需要多次借用self。但是,由于您尝试可变地借用self,编译器将不允许您这样做,因为您只是不可避免地借用了self部分(具体为self.jump_table })。

解决此问题的一种方法是将Chip8结构体拆分为较小的结构体,这样您就可以将所有必要的信息传递到func,而无需传入jump_table。< / p>