想练习一下Rust,尝试在struct Master里也建一个名叫work的的属性,类型为Option<Box<dyn FnMut(&Master)>>, 但是调用work(self)时有问题,想知道有没有办法把这段C++改写成Rust呢,谢谢
#include <vector>
#include <cstring>
#include <cstdlib>
#include <queue>
#include <algorithm>
#include <set>
#include <iostream>
#include <unistd.h>
#include <signal.h>
#include <functional>
using namespace std;
class Master {
public:
std::function<void(Master*)> work{};
int counter = 0;
void register_work(std::function<void(Master*)> w) {
work = w;
}
int increment() {
counter += 1;
return counter;
}
void run() {
if (!work) {
cout << "no work" << endl;
return;
}
work(this);
}
};
void simple_work(Master* master) {
while (true) {
sleep(1);
cout << master->increment() << endl;
}
}
int main() {
Master master;
master.register_work(simple_work);
master.run();
}
再贴一下我尝试写的Rust代码,但是编译不成功
use std::time::Duration;
struct Master {
counter: i32,
work: Option<Box<dyn Fn(&mut Master)>>,
}
impl Master {
fn new() -> Master {
Master {
counter: 0,
work: None,
}
}
fn increment(&mut self) {
self.counter += 1;
}
fn run(&mut self) {
let mut w = self.work.as_mut().unwrap();
w(self); // FIXME 这里始终不对,因为拿work用到了self的引用,不能再把self当参数传进去
}
fn register<F>(&mut self, f: F)
where
F: Fn(&mut Master) + 'static
{
self.work = Some(Box::new(f));
}
}
fn simple_work (m: &mut Master) {
loop {
std::thread::sleep(Duration::from_secs(2));
m.increment();
println!("{}", m.counter);
}
}
fn main() {
let mut m = Master::new();
m.register(simple_work);
m.run();
}
1
共 4 条评论, 1 页
评论区
写评论take
再放回去可行。但是更改一下程序结构感觉更好,
Master
和work
之间本来没有耦合,为什么要按照面向对象的思路将work
放在Master
里呢,将它们放在第三方不是更好吗。你的代码跟 https://zhuanlan.zhihu.com/p/405160594 他的有点像,文章也提供了一些更改的设计。
如果只是想要跑起来,至少可以这样
还有一个方案是把 work 限制成
fn(&mut Master)
虽然不能接受闭包了,但不需要 mut 就可以调用用 take ,操作完,再放回去。