【问题标题】:How can I use Rc::clone while casting to a trait object?如何在转换为特征对象时使用 Rc::clone?
【发布时间】:2021-07-12 06:00:54
【问题描述】:

Rust 书说使用 Rc::clone(&x) 而不是 x.clone()Rc 值是惯用的,因此很明显这不是典型的 clone。我完全赞成,但在实践中应用该理论时遇到了麻烦。

我想克隆一个引用计数的结构,但是将克隆转换为一个特征对象。我可以使用rc.clone() 做到这一点,但不能使用Rc::clone(&rc)。这……对我来说很奇怪。

struct ListView {}
trait View {}
impl View for ListView {}

fn very_contrived_example() {
    let list_view: Rc<ListView> = Rc::new(ListView {});
    let mut views: Vec<Rc<dyn View>> = Vec::new();

    // Using Rc::clone does not work:

    // error[E0308]: mismatched types
    //
    // views.push(Rc::clone(&list_view));
    //                      ^^^^^^^^^^ expected trait object `dyn View`, found struct `ListView`
    //
    // note: expected reference `&Rc<dyn View>`
    //          found reference `&Rc<ListView>`

    // Using a cast works in this very contrived example, but has the
    // disadvantage of moving `list_view`, for some reason, which is not
    // acceptable in general:
    // views.push(Rc::clone(&(list_view as Rc<dyn View>)));

    // But invoking it using method syntax works fine, without a move:
    views.push(list_view.clone());
}

Rc::clone(&amp;x)x.clone() 有什么区别? x.clone() 实际调用的是什么函数? self 的类型是什么?可以直接调用吗?

写这个的惯用方式是什么?

【问题讨论】:

    标签: rust trait-objects


    【解决方案1】:

    这是一种罕见的类型推断失败。显式传递正确的显式类型有效:

    views.push(Rc::<ListView>::clone(&list_view))
    

    问题在于Rc::clone(&amp;list_view) 根据预期类型(即Rc&lt;dyn View&gt;)而不是参数类型推断Rc&lt;T&gt; 中的T。另一方面,当您调用list_view.clone() 时,它使用Clonelist_view 类型的实现,因此它解析为Rc::&lt;ListView&gt;::clone


    如果上述问题在您的代码中经常出现,并且您希望在视觉上区分普通克隆和引用计数的浅克隆,您可以编写一个小辅助 trait:

    trait RcClone : Clone {
        fn rc_clone(&self) -> Self {
            self.clone()
        }
    }
    
    impl<T: ?Sized> RcClone for Rc<T> { }
    impl<T: ?Sized> RcClone for Arc<T> { }
    

    然后您可以在您的代码库中编写list_view.rc_clone(),这仅适用于引用计数类型。这仍然表明语义不同于常规克隆,但没有类型推断问题。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2023-04-01
      • 2019-09-21
      • 1970-01-01
      • 2019-10-23
      • 2015-11-23
      • 1970-01-01
      • 2021-05-24
      • 1970-01-01
      相关资源
      最近更新 更多