rust - 生命周期和实现克隆的问题
问题描述
我正在尝试定义一个表示可以使用不同算术运算组合的函数的结构(仅实现了加法)。
我想Clone
为我的结构实现,但是我似乎无法工作:
use std::ops::Add;
use std::boxed::Box;
use std::clone::Clone;
type InputT = i32;
type OutputT = f64;
pub struct ComposableFn<'a> {
f: Box<dyn 'a + Fn(InputT) -> OutputT>,
}
impl<'a> ComposableFn<'a> {
pub fn new<F: 'a + Fn(InputT) -> OutputT>(f: F) -> Self {
Self {
f: Box::new(f)
}
}
pub fn compute(&self, x: InputT) -> OutputT {
(self.f)(x)
}
}
impl<'a> Add<&'a ComposableFn<'a>> for &'a ComposableFn<'a> {
type Output = ComposableFn<'a>;
fn add(self, rhs: &'a ComposableFn) -> Self::Output {
ComposableFn::new(move |x| self.compute(x) + rhs.compute(x))
}
}
impl<'a> Clone for ComposableFn<'a> {
fn clone(&'a self) -> Self {
ComposableFn::new(move |x| self.compute(x))
}
}
fn main() {
let id = ComposableFn::new(|x| x.into());
println!("{}", id.compute(12));
let double = &id + &id;
println!("{}", double.compute(7));
let triple = &double + &id;
println!("{}", triple.compute(3));
}
编译时出现以下错误:
error[E0308]: method not compatible with trait
--> src/main.rs:33:5
|
33 | fn clone(&'a self) -> Self {
| ^^^^^^^^^^^^^^^^^^^^^^^^^^ lifetime mismatch
|
= note: expected fn pointer `fn(&ComposableFn<'a>) -> ComposableFn<'_>`
found fn pointer `fn(&'a ComposableFn<'a>) -> ComposableFn<'_>`
note: the anonymous lifetime #1 defined on the method body at 33:5...
--> src/main.rs:33:5
|
33 | fn clone(&'a self) -> Self {
| ^^^^^^^^^^^^^^^^^^^^^^^^^^
note: ...does not necessarily outlive the lifetime `'a` as defined on the impl at 32:6
--> src/main.rs:32:6
|
32 | impl<'a> Clone for ComposableFn<'a> {
| ^^
error: aborting due to previous error
删除'a
fromfn clone(&'a self)
会导致以下错误:
error[E0495]: cannot infer an appropriate lifetime due to conflicting requirements
--> src/main.rs:34:27
|
34 | ComposableFn::new(move |x| self.compute(x))
| ^^^^^^^^^^^^^^^^^^^^^^^^
|
note: first, the lifetime cannot outlive the anonymous lifetime #1 defined on the method body at 33:5...
--> src/main.rs:33:5
|
33 | fn clone(&self) -> Self {
| ^^^^^^^^^^^^^^^^^^^^^^^
note: ...so that the types are compatible
--> src/main.rs:34:27
|
34 | ComposableFn::new(move |x| self.compute(x))
| ^^^^^^^^^^^^^^^^^^^^^^^^
= note: expected `&ComposableFn<'_>`
found `&ComposableFn<'a>`
note: but, the lifetime must be valid for the lifetime `'a` as defined on the impl at 32:6...
--> src/main.rs:32:6
|
32 | impl<'a> Clone for ComposableFn<'a> {
| ^^
note: ...so that the expression is assignable
--> src/main.rs:34:9
|
34 | ComposableFn::new(move |x| self.compute(x))
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
= note: expected `ComposableFn<'a>`
found `ComposableFn<'_>`
error: aborting due to previous error
有没有办法解决这个问题?
解决方案
您不能Clone
以这种方式实施。Clone
要求返回类型完全匹配,这意味着完全相同的生命周期'a
。但是您正在尝试创建一个引用self
具有不同生命周期的克隆。
直接的解决方案是克隆f
。不幸的是,您不能克隆 a Box<dyn...>
,至少在没有帮助的情况下不能。请参阅:如何克隆存储盒装特征对象的结构?
唯一直接的解决方案是交换Box
,Rc
以便他们共享所有权:
use std::rc::Rc;
pub struct ComposableFn<'a> {
f: Rc<dyn 'a + Fn(InputT) -> OutputT>,
}
impl Clone for ComposableFn<'_> {
fn clone(&self) -> Self {
ComposableFn { f: self.f.clone() }
}
}
推荐阅读
- sql - 如何在 SQLite 中选择 sqlite "check ... in [list]" 选项?
- php - 如何获取单列的一维数组中的数据?
- python - Pytesseract 读取彩色文本
- javascript - Javascript 在传递给 C# 控制器时将日期转换为 UTC
- android - Webview导致页面上各种元素的背景图像变黑
- visual-studio-code - VS Code - 打开 Project Explorer 更深一层以显示类
- python - 有效地找到下一个星期五 13 号
- python - Plotly:如何在带注释的热图中舍入显示文本但在悬停时保持完整格式?
- kubernetes - 有没有办法使用 Prometheus 本身监控 timescaleDB statefulset pod?
- git - 在 python 项目中保存非代码相关文件(参考文件/测试资产)的正确方法是什么?