繁体   English   中英

为什么不能借用盒装结构作为特征?

[英]Why can't a boxed struct be borrowed as a trait?

给定实现特征T的结构S ,为什么Box<S>实现Borrow<dyn T>

我本来希望编译的以下代码不会:

trait T{}
struct S{}
impl T for S{}

fn f1(s: &S) -> &dyn T {
    s
}

fn f2(s: &Box<S>) -> &dyn T {
    std::borrow::Borrow::borrow(s)
}

为什么f1编译而f2不编译? (从&S&dyn T的转换在第一种情况下完成,而不是在第二种情况下完成)。

这与类型推断和类型强制工作的方式有关。 Borrow<B>特征的参数是借入值的类型,类型检查器需要知道它的含义。

如果您只写:

std::borrow::Borrow::borrow(s)

然后从周围的代码中推断出Borrow<B>的类型B 在您的情况下,可以推断为dyn T因为这是返回值。 但是, dyn T是与S完全不同的类型,因此不进行类型检查。

一旦类型检查器知道返回的值是&S类型&S则可以将其强制为&dyn T ,但是您需要提供以下信息:

fn f2(s: &Box<S>) -> &dyn T {
    let s: &S = std::borrow::Borrow::borrow(s);
    s
}

或者,更简洁地说:

fn f2(s: &Box<S>) -> &dyn T {
    std::borrow::Borrow::<S>::borrow(s)
}

SébastienRenauld的答案之所以起作用,是因为Deref使用关联的类型而不是类型参数。 类型检查器可以轻松推断<S as Deref>::Target因为每种类型只能有一个Deref实现,并且关联的Target类型是唯一确定的。 Borrow有所不同,因为Box<S> 可以实现Borrow<()>Borrow<i32>Borrow<Box<Option<Vec<bool>>>> ,...,因此您必须更明确地了解打算实现的实现。

&Box<S>不直接等于Box<&S> ,这就是为什么它不直接编译。

您可以通过取消引用相对容易地解决此问题,如下所示:

use std::ops::Deref;
trait T{}
struct S{}
impl T for S{}

fn f1(s : &S) -> &(dyn T) {
    s
}

fn f2(s : &Box<S>) -> &(dyn T) {
    s.deref()
}

(特质Deref的存在使可读性稍微容易一些)

deref()的调用是通过&self ,因此具有&Box<S>足以调用它。 它仅返回&S ,并且由于实现T所以类型检出。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM