我正在尝试根据条件选择要调用的函数。我想将该函数存储在一个变量中,这样我以后可以再次调用它而不需要携带条件。这是一个有用的最小例子:
Selector< std::is_pointer<T>::value, std::is_arithmetic<T>::value >()
我的问题是:是否有可能摆脱中间变量?我试过简单地删除它们:
constexpr
然后借用检查员抱怨借用的值只有在比赛结束前才有效(顺便说一下,为什么?函数是shift
无论如何都应该有效到时间结束)。我还尝试使用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();
}
生命周期,但这也不起作用。
答案 0 :(得分:5)
如果您只需要使用静态函数而不是闭包,则以下工作:
fn foo() {
println!("Foo");
}
fn bar() {
println!("Bar");
}
fn main() {
let selector = 0;
let test: fn() = match selector {
0 => foo,
_ => bar
};
test();
}
(试试playground)
这里我使用的是函数类型而不是函数特征。
借用的特质对象不起作用的原因可能如下。任何特征对象都是一个胖指针,它由指向某个值的指针和指向虚拟表的指针组成。当从闭包创建trait对象时,一切都很清楚 - 值将由闭包本身表示(内部是包含所有捕获变量的结构的实例),虚拟表将包含指向实现的实现编译器生成的相应Fn*()
特征,其主体将是封闭体。
但是,有了功能,事情就不那么清楚了。创建特征对象没有价值,因为函数本身应该对应Fn()
特征的实现。因此,rustc可能会生成一个空结构并为它实现Fn()
,这个实现直接调用静态函数(不是实际的Rust,但是接近):
struct SomeGeneratedStructFoo;
impl Fn<()> for SomeGeneratedStructFoo {
type Output = ();
fn call(&self, args: ()) -> () {
foo();
}
}
因此,当从fn foo()
创建特征对象时,实际上会引用类型SomeGeneratedStructFoo
的临时值。但是,此值是在匹配内创建的,并且只会从匹配中返回对它的引用,因此该值的持续时间不够长,而且该错误的含义是什么。
答案 1 :(得分:1)
fn()
是函数指针类型。它的已经指针类型。您可以使用std::mem::size_of::<fn()>()
进行检查。它不是零大小的类型。
执行&foo
时,会获取指向堆栈分配指针的指针。这个内部指针不会存在很长时间,导致错误。
您可以按照建议将这些转换为通用fn()
类型。不过,我很想知道为什么你不能将fn()
投射到&Fn()
。