如何从 Rust 的特征中获取函数指针?

use*_*861 3 function-pointers rust

我该如何克服这样的事情:

struct Test {
    foo: Option<fn()>
}

impl Test {
    fn new(&mut self) {
        self.foo = Option::Some(self.a);
    }

    fn a(&self) { /* can use Test */ }
}
Run Code Online (Sandbox Code Playgroud)

我收到此错误:

struct Test {
    foo: Option<fn()>
}

impl Test {
    fn new(&mut self) {
        self.foo = Option::Some(self.a);
    }

    fn a(&self) { /* can use Test */ }
}
Run Code Online (Sandbox Code Playgroud)

如何从特征传递函数指针?类似于本例中会发生的情况:

impl Test {
    fn new(&mut self) {
        self.foo = Option::Some(a);
    }
}

fn a() { /* can't use Test */ }
Run Code Online (Sandbox Code Playgroud)

DK.*_*DK. 5

您在这里尝试做的是从(这里使用 Python 术语,因为 Rust 没有这个词)绑定方法获取函数指针。你不能。

首先,因为 Rust 没有“绑定”方法的概念;.也就是说,您不能引用已绑定到位的调用者( 左侧的内容)的方法。如果你想构造一个近似于此的可调用函数,你可以使用闭包;IE || self.a()

然而,这仍然行不通,因为闭包不是函数指针。没有像其他语言那样的可调用事物的“基本类型”。函数指针是一种单一的、特定的可调用类型;闭包完全不同。相反,有一些特征(在实现时)使类型可调用。它们是FnFnMut、 和FnOnce。因为它们是特征,所以您不能将它们用作类型,而必须从某个间接层后面使用它们,例如Box<FnOnce()>or &mut FnMut(i32) -> String

现在,您可以更改Test为存储 an Option<Box<Fn()>>,但这仍然没有帮助。这是因为另一个问题:您试图在其内部存储对结构的引用。这不会起到很好的作用。如果您设法做到这一点,您实际上会导致该Test值永久无法使用。更有可能的是编译器不会让你走到这一步。

旁白:你可以做到这一点,但不能不诉诸引用计数和动态借用检查,这超出了这里的范围。

所以你所问问题的答案是:你不知道。

让我们改变一下问题:我们可以存储一个根本不尝试捕获调用者的可调用函数,而不是尝试插入自引用闭包。

struct Test {
    foo: Option<Box<Fn(&Test)>>,
}

impl Test {
    fn new() -> Test {
        Test {
            foo: Option::Some(Box::new(Self::a)),
        }
    }

    fn a(&self) { /* can use Test */ }

    fn invoke(&self) {
        if let Some(f) = self.foo.as_ref() {
            f(self);
        }
    }
}

fn main() {
    let t = Test::new();
    t.invoke();
}
Run Code Online (Sandbox Code Playgroud)

存储的可调用现在是一个显式调用调用者的函数,回避了循环引用的问题。Test::a我们可以通过将其称为自由函数来直接使用它来存储。另请注意,因为Test是实现类型,所以我也可以将其称为Self.

旁白:我还纠正了你的Test::new功能。Rust 没有构造函数,只有像其他函数一样返回值的函数。

如果您确信自己永远不想将闭包存储在 中foo,则可以替换Box<Fn(&Test)>fn(&Test)。这将您限制为函数指针,但避免了额外的分配。

如果您还没有阅读过Rust Book ,我强烈建议您阅读一下。