我正在尝试向结构添加一个函数指针,但无法弄清楚如何执行它。这是一个简单的例子:
struct Ure<'a> {
num: u64,
func: Option<&'a Fn(u64) -> u64>,
}
impl<'a> Ure<'a> {
fn g42_ure(n: u64) -> Ure<'a> {
Ure {
num: n,
func: Some(&Ure::g42),
}
}
fn g42(u: u64) -> u64 {
if u > 42 { u } else { 42 }
}
}
这会导致以下错误:
error: borrowed value does not live long enough
--> <anon>:10:23
|
10 | func: Some(&Ure::g42),
| ^^^^^^^^ does not live long enough
11 | }
12 | }
| - temporary value only lives until here
|
note: borrowed value must be valid for the lifetime 'a as defined on the body at 7:34...
--> <anon>:7:35
|
7 | fn g42_ure(n: u64) -> Ure<'a> {
| ___________________________________^ starting here...
8 | | Ure {
9 | | num: n,
10 | | func: Some(&Ure::g42),
11 | | }
12 | | }
| |_____^ ...ending here
有没有办法在这个示例中获得对函数g42
的引用,以便将其作为g42_ure
的参数传递给自己足够长的时间?对于定义g42
的位置(无论是在impl Ure
,g42_ure()
内还是两者都没有),对我来说无关紧要,但是从OOP背景来看它似乎在impl Ure
内更整洁。
我只是在学习Rust(非常喜欢它),所以任何帮助都会受到赞赏,谢谢。
答案 0 :(得分:4)
类型Fn(u64) -> u64
不是函数指针,而是特征(-object)。 Rust中的函数指针写为fn(u64) -> u64
,其中小写f
!另请注意,fn(u64) -> u64
已一个函数指针,无需说&fn(u64) -> u64
!
因此,使其工作的一种方法是使用函数指针(Playground):
struct Ure {
num: u64,
func: Option<fn(u64) -> u64>,
// ^^^^^^^^^^^^^^
}
impl Ure {
fn g42_ure(n: u64) -> Ure {
Ure {
num: n,
func: Some(Ure::g42),
// ^^^^^^^^
}
}
// ...
}
但是,函数指针有局限性。具体来说,他们不能拥有像闭包这样的环境。那里有Fn
特征(与其兄弟姐妹FnMut
和FnOnce
一起)在可调用事物(包括函数指针和闭包)上进行抽象。
问题是你不能轻易使用特质对象。可能最简单的方法是使用Box
来存储和拥有堆上的特征对象。它看起来像这样(Playground):
struct Ure {
num: u64,
func: Option<Box<Fn(u64) -> u64>>,
// ^^^^^^^^^^^^^^^^^^^
}
impl Ure {
fn g42_ure(n: u64) -> Ure {
Ure {
num: n,
func: Some(Box::new(Ure::g42)),
// ^^^^^^^^^^^^^^^^^^
}
}
// ...
}