![](/img/trans.png)
[英]Why can't I create a trait object with let _: Arc<dyn Trait> = value.into()?
[英]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.