【问题标题】:Problem with lifetimes and implementing Clone生命周期和实现克隆的问题
【发布时间】:2020-11-23 23:51:07
【问题描述】:

我正在尝试定义一个表示函数的结构,该函数可以使用不同的算术运算组合(仅实现了加法)。

我想为我的结构实现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

fn clone(&amp;'a self) 中删除'a 会导致以下错误:

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

有没有办法解决这个问题?

【问题讨论】:

    标签: rust lifetime


    【解决方案1】:

    您不能以这种方式实现CloneClone 要求返回类型完全匹配,这意味着完全相同的生命周期'a。但是您正在尝试创建一个引用 self 的克隆,它的生命周期不同

    直接的解决方案是克隆f。不幸的是,你不能克隆Box&lt;dyn...&gt;,至少在没有帮助的情况下不能。见:How to clone a struct storing a boxed trait object?

    唯一直接的解决方案是将BoxRc 交换,以便他们共享所有权:

    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() }
        }
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2015-11-15
      • 2016-09-26
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多