为了学习Rust语言,我正在使用一个旧的C++库,我已经躺在那里并尝试将其转换为Rust.它使用了很多C++ 11闭包,我在翻译概念方面遇到了一些困难.
在C++中我有这样的事情:
// library.h
struct Event {
// just some data
};
class Object {
public:
// ...
std::function<void(Event&)>& makeFunc(std::string& s) {
return m_funcs[s];
}
// ...
private:
// ...
std::map<std::string, std::function<void(Event&)>> m_funcs;
// ...
};
// main.cpp using the library
int main()
{
Object foo;
foo.makeFunc("func1") = [&]{
// do stuff
};
return 0;
}
Run Code Online (Sandbox Code Playgroud)
我遇到问题的部分是将函数正确存储在Rust HashMap集合中.我试过这个:
struct Event;
struct Object {
m_funcs : HashMap<String, FnMut(&Event)>
}
impl Object {
// send f as another parameter rather than try and return borrow
// compiler was complaining
fn makeFunc(&mut self, s : &str,f: FnMut(&Event)) {
self.m_funcs.insert(String::from_str(s), f);
}
}
Run Code Online (Sandbox Code Playgroud)
但它说 the trait core::marker::Sized is not implemented for the type 'for('r) core::ops::FnMut(&'r CreateEvent)'
这是有道理的,因为它FnMut
是一个特征,因此在编译时没有已知的HashMap大小.所以我认为hashmap需要一个实际的指针而不是一个抽象类型.所以我把它改成了这个
struct Object {
m_funcs : HashMap<String, Box<FnMut(&Event)>>
}
impl Object {
fn makeFunc(&mut self, s : &str, f: &FnMut(&Event)) {
self.m_funcs.insert(String::from_str(s), Box::new(f));
}
}
Run Code Online (Sandbox Code Playgroud)
现在它the trait 'for('r) core::ops::Fn<(&'r CreateEvent,)>' is not implemented for the type '&for('r) core::ops::FnMut(&'r CreateEvent)' [E0277]
在插入处说.这个错误对我来说毫无意义.有人可以向我解释在HashMap中存储对非转义闭包的引用的正确方法吗?
你已经采取了&FnMut(&Event)
一个特性对象 - 并且在装箱后,希望将其存储为Box<FnMut(&Event)>
.因此,你需要的是&FnMut(&Event)
必须实现的FnMut(&Event)
,它不会(并明确不能用于FnMut.call_mut
需要&mut self
).
你想要的是采用一种实现 的任意类型FnMut(&Event)
- 即使用泛型 - 并按值获取它.签名就是这样的:
fn make_func<F: FnMut(&Event)>(&mut self, s: &str, f: F)
Run Code Online (Sandbox Code Playgroud)
然而,由于生命周期,它比这更复杂,但是你想做的事情可能会有所不同; 在HashMap中存储带有引用arg的未装箱闭包有关于该主题的更多信息.这是我认为你最想要的东西:
struct Object<'a> {
m_funcs: HashMap<String, Box<FnMut(&Event) + 'a>>,
}
impl<'a> Object<'a> {
fn make_func<F: FnMut(&Event) + 'a>(&mut self, s: &str, f: F) {
self.m_funcs.insert(String::from_str(s), Box::new(f));
}
}
Run Code Online (Sandbox Code Playgroud)
如果您乐意不让任何闭包捕获对其环境的引用,您可以删除所有'a
赞成只有一个+ 'static
绑定F
.
归档时间: |
|
查看次数: |
2063 次 |
最近记录: |