我有以下代码尝试从盒装特征中引用特征对象:
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>
?
答案 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强制”;也就是说,它会反复取消引用值,直到类型匹配,或者不能再进一步取消引用。
另一方面,强制转移到特征对象根本不使用解除引用;它涉及直接从给定的一个构造一个新的指针。如果它不能那样做,那就失败了。