动态选择要在没有中间变量的情况下调用的函数

时间:2015-10-01 10:38:14

标签: rust

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

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(); } 生命周期,但这也不起作用。

2 个答案:

答案 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()