繁体   English   中英

为什么我不能在 Rc 中使用这个闭包<dyn Fn()> ?

[英]Why can't I use this closure inside a Rc<dyn Fn()>?

我有这个结构:

pub struct ImmEval<Out> {
    closure: Rc<dyn Fn(&Self) -> Out>
}
impl<Out> From<Rc<dyn Fn(&Self) -> Out>> for ImmEval<Out> {
    /// Constructs the evaluator from the specified closure.
    fn from(cl: Rc<dyn Fn(&Self) -> Out>) -> Self {
        ImmEval {closure: cl}
    }
}
impl<Out> Evaluator for ImmEval<Out> {
    type Output = Out;
    /// Evaluates and returns the result.
    fn eval(&self) -> Self::Output {
        (*self.closure)(self)
    }
}

在这样的测试中使用:

let counter = Cell::new(0);
{
    let eval = ImmEval::<i32>::from(Rc::from(|_: &ImmEval<i32>| {
        counter.set(counter.get() + 1);
        counter.get()
    }));

    eval.eval();
    eval.eval();
}
assert_eq!(counter.get(), 2);

结构本身会编译,但测试不会。 相反,它失败并显示以下rustc消息:

error[E0277]: the trait bound `ImmEval<i32>: std::convert::From<std::rc::Rc<[closure@src\tests.rs:8:51: 11:10 counter:_]>>` is not satisfied
  --> src\tests.rs:8:41
   |
8  |           let eval = ImmEval::<i32>::from(Rc::from(|_: &ImmEval<i32>| {
   |  _________________________________________^
9  | |             counter.set(counter.get() + 1);
10 | |             counter.get()
11 | |         }));
   | |__________^ the trait `std::convert::From<std::rc::Rc<[closure@src\tests.rs:8:51: 11:10 counter:_]>>` is not implemented for `ImmEval<i32>`
   |
   = help: the following implementations were found:
             <ImmEval<Out> as std::convert::From<std::rc::Rc<(dyn for<'r> std::ops::Fn(&'r ImmEval<Out>) -> Out + 'static)>>>
   = note: required by `std::convert::From::from`

这当然意味着我的闭包不是有效的Fn(&ImmEval<i32>) -> i32 ,但为什么呢?

这是操场示例

在这种情况下无法进行类型推断。 如果你写你想要的类型,它的工作原理:

let f: Rc<dyn Fn(&ImmEval<i32>) -> i32> = Rc::new(|_: &ImmEval<i32>| {
    counter.set(counter.get() + 1);
    counter.get()
});
let eval = ImmEval::<i32>::from(f);

但这并不能解决您一生中的其他问题。

一个比单独创建闭包更优雅的解决方案(如这里所见,尽管我仍然很欣赏对问题的出色解释)根本不使用From特征:

impl<'l, Out> ImmEval<'l, Out> {
    pub fn new<Cl>(closure: Cl) -> Self
    where Cl: (Fn(&ImmEval<Out>) -> Out) + 'l {
        let rcl: Rc<dyn Fn(&ImmEval<Out>) -> Out> = Rc::from(closure);
        ImmEval {closure: rcl}
    }
}

我用一个通用的new替换了From构造函数(并且还添加了一些生命周期说明符以确保闭包存在足够长的时间),它获取闭包本身(没有引用计数器)并以与第一个相同的方式将其放入一个我提到的答案确实如此。 然后通过克隆评估器结构或添加方法get_closure ,可以提取和重用引用计数闭包。 此外,如果保留了From特征,那么get_closure结果将可以与提到的第一个答案相同的方式使用。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM