[英]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.