gpt4 book ai didi

rust - 动态选择要调用的函数,无需中间变量

转载 作者:行者123 更新时间:2023-11-29 07:43:23 24 4
gpt4 key购买 nike

我正在尝试根据条件选择要调用的函数。我想将该函数存储在一个变量中,以便稍后可以再次调用它而无需携带条件。这是一个最小的工作示例:

fn foo() {
println! ("Foo");
}
fn bar() {
println! ("Bar");
}

fn main() {
let selector = 0;

let foo: &Fn() = &foo;
let bar: &Fn() = &bar;
let test = match selector {
0 => foo,
_ => bar
};
test();
}

我的问题是:是否可以去掉中间变量?我试过简单地删除它们:

fn foo() {
println! ("Foo");
}
fn bar() {
println! ("Bar");
}

fn main() {
let selector = 0;

let test = match selector {
0 => &foo as &Fn(),
_ => &bar as &Fn()
};
test();
}

但是随后借用检查器提示说借用的值只在匹配结束之前有效(顺便说一句,为什么?函数是'static 无论如何应该有效到时间结束) .我还尝试通过使用 &foo as &'static Fn() 使 'static 生命周期显式化,但这也不起作用。

最佳答案

如果您只需要使用静态函数而不是闭包,则以下方法有效:

fn foo() {
println!("Foo");
}

fn bar() {
println!("Bar");
}

fn main() {
let selector = 0;

let test: fn() = match selector {
0 => foo,
_ => bar
};

test();
}

(试穿playground)

这里我使用了函数类型而不是函数特征。

借来的trait对象不起作用的原因大概有以下几点。任何特征对象都是一个胖指针,由指向某个值的指针和指向虚拟表的指针组成。当 trait 对象从闭包中创建时,一切都很清楚——值将由闭包本身表示(在内部是包含所有捕获变量的结构的实例)并且虚拟表将包含指向实现的指针编译器生成的相应 Fn*() 特征,其主体将是闭包主体。

然而,对于函数,事情就不是那么清楚了。从中创建特征对象没有值(value),因为函数本身应该对应于 Fn() 特征的实现。因此,rustc 可能会生成一个空结构并为其实现 Fn(),并且此实现直接调用静态函数(不是实际的 Rust,而是接近的东西):

struct SomeGeneratedStructFoo;

impl Fn<()> for SomeGeneratedStructFoo {
type Output = ();
fn call(&self, args: ()) -> () {
foo();
}
}

因此,当通过 fn foo() 创建特征对象时,实际上会引用一个类型为 SomeGeneratedStructFoo 的临时值。然而,这个值是在匹配中创建的,并且只从匹配中返回对它的引用,因此这个值的生命周期不够长,这就是错误的原因。

关于rust - 动态选择要调用的函数,无需中间变量,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/32885446/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com