如何将盒装特征转换为特征参考?

时间:2018-03-11 09:19:56

标签: rust

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

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`

如何从&T正确借用Box<T>

2 个答案:

答案 0 :(得分:5)

Box<T>实现the AsRef<T> trait,它提供方法as_ref(),因此您可以将其转换为引用方式:

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

通常,deref coercions意味着您通常不需要明确地写出来。如果将类型Box<T>的值传递给带&T的函数,编译器将为您插入转换。如果要调用T&self之一的方法,编译器将为您插入转换。 但是,deref强制不适用于特征,因此特征对象不会发生这种情况。

答案 1 :(得分:4)

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

let trait_ref: &T = &*trait_box;

涉及&S的行有效的原因是Rust从Box<S>&S的唯一方法是通过“deref强制”;也就是说,它会反复取消引用值,直到类型匹配,或者不能再进一步取消引用。

另一方面,强制转移到特征对象根本不使用解除引用;它涉及直接从给定的一个构造一个新的指针。如果它不能那样做,那就失败了。