我正在努力取代proc。使用Invoke
有效,但我必须指定生命周期。为了能够将枚举发送到另一个线程,我必须使用'static
和更晚的mem::transmute
来转换生命周期。不太吸引人。
另一方面,使用FnOnce
给出了这个错误:
<anon>:24:32: 24:33 error: cannot move a value of type for<'r> core::ops::FnOnce(&'r Type) + Send: the size of for<'r> core::ops::FnOnce(&'r Type) + Send cannot be statically determined [E0161]
如何正确替换proc?
#![feature(box_syntax)]
#![feature(std_misc)]
use std::mem;
use std::thunk::Invoke;
struct Type;
enum Message {
Handle(Box<Invoke<(&'static Type)> + Send>) //'
}
enum Message2 {
Handle(Box<FnOnce(&Type) + Send>)
}
pub fn main() {
let a = Type;
let handler = Message::Handle(box move |_| {});
let handler2 = Message2::Handle(box move |_| {});
match handler {
Message::Handle(f) => f.invoke(unsafe {mem::transmute(&a)})
}
match handler2 {
Message2::Handle(f) => f(&a)
}
}
答案 0 :(得分:3)
如何使用Thunk
?
#![feature(std_misc)]
use std::thunk::Thunk;
struct Type;
enum Message<'a> { //'
Handle(Thunk<'a, &'a Type, u8>)
}
pub fn main() {
let a = Type;
let handler = Message::Handle(Thunk::with_arg(move |_| 42));
let res = match handler {
Message::Handle(f) => f.invoke((&a))
};
println!("{}", res);
}
为了能够将枚举发送到另一个线程,我必须使用&#39;静态和后来的mem :: transmute来转换生命周期。
自RFC 458登陆以来,thread::scoped
可以接受非Fn*
生命周期的闭包(和'static
特征)。需要注意的是,您必须确保线程在生命周期到期之前退出 - 否则您将引用无效的内存!
使用mem::transmute
可以忽略这一点,但代价是当内存不再有效时程序崩溃。
答案 1 :(得分:2)
您的案例中的解决方案是使用for
关键字,该关键字允许您为输入参数指定“匿名”生命周期。
#![feature(box_syntax)]
#![feature(std_misc)]
use std::thunk::Invoke;
struct Type;
enum Message {
Handle(Box<for <'r> Invoke<(&'r Type)> + Send>)
}
pub fn main() {
let a = Type;
let handler = Message::Handle(box move |_: &Type| {});
match handler {
Message::Handle(f) => f.invoke(&a)
}
}
此外,我认为使用transmute()
技巧时的主要问题是,如果您的函数正在返回或存储对输入结构的一部分的引用:编译器会为此引用分配'静态生存期,但显然这是一个错误,可能会导致内存损坏。
您可以在this blog post中找到有关闭包的更多信息以及当前需要Invoke
特征的原因(注意:显式指定闭包类型的部分现已过时,编译器现在推断它)。
答案 2 :(得分:0)
简单的答案是,使用:
Handle(Box<FnMut(&Type) + Send>)
更复杂的答案是,根据https://github.com/rust-lang/rust/blob/master/src/test/run-pass/unboxed-closures-prelude.rs,您无法调用Box<FnOnce(...)>
,只能调用大小F,其中F:FnOnce&lt; ...&gt;
......不知道为什么,但我推测它是因为它随着特质消耗自我而移动了价值;很奇怪。