【问题标题】:FnOnce inside Enum: cannot move out of borrowed contentEnum 中的 FnOnce:无法移出借用的内容
【发布时间】:2015-08-26 20:47:31
【问题描述】:

我是 rust 新手,但在所有权/借款方面仍有一些问题。在这种情况下,我想将 FnOnce 存储在枚举中,然后稍后从另一个线程调用它。我尝试了很多不同的变体,但总是卡在某个地方。这是我目前拥有的简化版本:

#![feature(fnbox)]

use std::sync::{Arc, Mutex};
use std::boxed::{Box, FnBox};

enum Foo<T> {
    DoNothing,
    CallFunction(Box<FnBox(&T) + Send>)
}

struct FooInMutex<T> {
    foo: Arc<Mutex<Foo<T>>>
}

impl<T> FooInMutex<T> {
    fn put_fn(&self, f: Box<FnBox(&T)+Send>) {
        let mut foo = self.foo.lock().unwrap();
        let mut new_foo : Foo<T>;
        match *foo {
            Foo::DoNothing =>
                new_foo = Foo::CallFunction(f),
            _ =>
                new_foo = Foo::DoNothing
        }
        *foo = new_foo;
    }

    fn do_it(&self, t: T) {
        let mut foo = self.foo.lock().unwrap();
        let mut new_foo : Foo<T>;
        match *foo {
            Foo::CallFunction(ref mut f) => {
                //f(&t)
                f.call_box((&t,));
                new_foo = Foo::DoNothing;
            }
            _ =>
                panic!("...")
        }
        *foo = new_foo;
    }
}

#[test]
fn it_works() {
    let x = FooInMutex { foo: Arch::new(Mutex::new(Foo::DoNothing)) };

    x.put_fn(Box::new(|| panic!("foo"))); 
    x.do_it();
}

我使用“rustc 1.4.0-nightly (e35fd7481 2015-08-17)”。 错误信息:

src/lib.rs:35:17: 35:18 error: cannot move out of borrowed content
src/lib.rs:35                 f.call_box((&t,));
                              ^

据我了解,f 归互斥锁中的枚举所有,我只通过 *foo 借用它。但是为了调用f,我需要把它移开。但是如何做到这一点?或者我还需要进行哪些更改才能使此示例正常运行?

【问题讨论】:

    标签: rust


    【解决方案1】:

    std::mem::replace 是你应该在那里使用的,像这样:

    use std::mem;
    
    …
    
        fn do_it(&self, t: T) {
            match mem::replace(self.foo.lock().unwrap(), Foo::DoNothing) {
                Foo::CallFunction(f) => {
                    f.call_box((&t,));
                }
                _ => panic!("...")
            }
        }
    

    【讨论】:

    • 文档参考:std::mem::replace
    • 你能解释一下为什么它一开始就不起作用吗?为什么f需要移出?
    • @tafia:FnBox基于FnOnce,消耗闭包环境;也就是说,f.call_box 按值获取self,因此f 必须是Box&lt;FnBox(&amp;T) + Send&gt;。对此的可变引用是不够的,而可变引用是您在初始示例中所拥有的全部(因此“不能移出借用的上下文”,它试图将 Box&lt;FnBox(&amp;T) + Send&gt; 移出可变引用)。
    • @Chris Morgan:谢谢!!值得为下一位读者提供答案
    猜你喜欢
    • 2018-04-04
    • 1970-01-01
    • 1970-01-01
    • 2015-03-25
    • 1970-01-01
    • 2017-10-15
    • 2015-04-20
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多