簡體   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