【问题标题】:How to convert a boxed trait into a trait reference?如何将盒装特征转换为特征参考?
【发布时间】:2018-08-19 11:37:05
【问题描述】:

我有以下代码尝试从盒装特征中获取对特征对象的引用:

trait T {}

struct S {}

impl T for S {}

fn main() {
    let struct_box: Box<S> = Box::new(S {});
    let struct_ref: &S = &struct_box;

    let trait_box: Box<T> = Box::new(S {});
    let trait_ref: &T = &trait_box;
}

编译器返回以下错误:

error[E0277]: the trait bound `std::boxed::Box<T>: T` is not satisfied
  --> src/main.rs:12:25
   |
12 |     let trait_ref: &T = &trait_box;
   |                         ^^^^^^^^^^ the trait `T` is not implemented for `std::boxed::Box<T>`
   |
   = note: required for the cast to the object type `T`

如何从Box&lt;T&gt;正确借用&amp;T

【问题讨论】:

标签: rust


【解决方案1】:

Box&lt;T&gt; 实现了the AsRef&lt;T&gt; trait,它提供了方法as_ref(),所以你可以这样把它变成一个引用:

let trait_ref: &T = trait_box.as_ref();

通常,deref coercions 表示您通常不需要明确地写出来。如果您将Box&lt;T&gt; 类型的值传递给采用&amp;T 的函数,编译器将为您插入转换。如果您想调用T 上采用&amp;self 的方法之一,编译器将为您插入转换。 但是,deref 强制不适用于对 trait 对象类型的强制转换(编译器将选择一个未调整大小的强制,这就是您的示例中发生的情况)。

【讨论】:

    【解决方案2】:

    借用Box的内容,而不是Box本身:

    let trait_ref: &T = &*trait_box;
    

    涉及&amp;S 的行起作用的原因是,Rust 从Box&lt;S&gt;&amp;S 的唯一方法是通过“deref coercion”;也就是说,它重复地取消引用该值,直到类型匹配,或者它不能进一步取消引用。

    另一方面,强制转换为 trait 对象根本不是使用解引用完成的;它涉及直接从给定的指针构造一个新指针。如果它不能这样做,它就会失败。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2017-05-23
      • 1970-01-01
      • 1970-01-01
      • 2022-01-05
      • 2015-08-07
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多