调用Rust中存储在结构中的堆栈分配的闭包 [英] Calling a Stack-Allocated Closure Stored in a Struct in Rust
问题描述
我将闭包存储在这样的结构中:
#[derive(Clone)]结构S< a>{func:&'a FnOnce()->u32}fn main(){令s = S {func:& ||0};let val =(s.func)();println!("{}",val);}
编译时, s.func
无法移动以执行自身.我知道为什么不能移动它(即,它仅是一个引用,并且在编译时不知道其大小),但不知道为什么要移动它-仅仅是因为闭包是通过traits实现的?/p>
这是错误消息:
错误[E0161]:无法移动类型为std :: ops :: FnOnce()->的值.u32:std :: ops :: FnOnce()的大小->无法静态确定u32->main.rs:8:15|8 |let val =(s.func)();|^^^^^^^^^错误[E0507]:无法移出借用的内容->main.rs:8:15|8 |let val =(s.func)();|^^^^^^^^^无法移出借用的内容错误:由于2个先前的错误而中止
这是解决此问题的唯一方法吗(通过 Box< Box< FnOnce()-> u32>
)存储在堆上?为什么调用闭包会移动它呢?大概调用它不会改变函数本身.
由于 take
-在调用 Option
之前将其关闭.>
如果您可能多次调用该闭包,或者您不想获得该闭包的所有权,或者您不想让该结构成为闭包类型的泛型,则应该使用Fn
或 FnMut
. Fn :: call
通过引用和 FnMut :: call_mut
通过可变引用获取 self
.由于两者都接受引用,因此可以将特征对象与它们一起使用.
I am storing a closure in a struct like this:
#[derive(Clone)]
struct S<'a> {
func: &'a FnOnce() -> u32
}
fn main() {
let s = S { func: &|| 0 };
let val = (s.func)();
println!("{}", val);
}
When I compile, s.func
cannot be moved to execute itself. I understand why it cannot be moved (namely that it's only a reference and that its size is not known at compile time), but don't know why it's being moved at all -- is it just because closures are implemented via traits?
Here's the error message:
error[E0161]: cannot move a value of type std::ops::FnOnce() -> u32:
the size of std::ops::FnOnce() -> u32 cannot be statically determined
--> main.rs:8:15
|
8 | let val = (s.func)();
| ^^^^^^^^
error[E0507]: cannot move out of borrowed content
--> main.rs:8:15
|
8 | let val = (s.func)();
| ^^^^^^^^ cannot move out of borrowed content
error: aborting due to 2 previous errors
Is this only way the solve this to store the closure on the heap (via Box<FnOnce() -> u32>
)? And why does calling a closure move it? Presumably calling it doesn't mutate the function itself.
The closure is being moved because FnOnce::call_once
takes self
by value. This contract enforces the guarantee that the function will not be called more than once.
If you will indeed be calling the closure at most once, and you want to use the FnOnce
trait, then your struct needs to take ownership of that closure (and you will need to make your struct generic on the closure type). Note that calling the closure will move the closure out of your struct, thereby invalidating the whole struct; you may work around that by wrapping the FnOnce
in an Option
and take
-ing the closure out of the Option
before calling it.
If you might be calling the closure more than once, you don't want to take ownership of the closure, or you don't want to make your struct generic on the closure type, then you should use either Fn
or FnMut
instead. Fn::call
takes self
by reference and FnMut::call_mut
takes self
by mutable reference. Since both accept references, you can use trait objects with them.
这篇关于调用Rust中存储在结构中的堆栈分配的闭包的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!