簡體   English   中英

Rust不會讓我從匹配中返回某個類型的實例,一直在想我正在嘗試返回一個值

[英]Rust won't let me return an instance of a type from a match, keeps thinking I'm trying to return a value

根據這個答案這個問題 ,我需要做下面的返回一個實例Trait

trait Shader {}

struct MyShader;
impl Shader for MyShader {}

struct GraphicsContext;

impl GraphicsContext {
    fn create_shader(&self) -> impl Shader {
        let shader = MyShader;
        shader
    }
}

但是當我嘗試這樣做時:

pub trait Component { }

struct Kind {}

struct Location {}

impl Component for Kind {}

impl Component for Location {}

pub fn get(comp_name: &String) -> impl Component {
    match comp_name.as_ref() {
        "kind"      => Kind,
        "location"  => Location
    }
}

我剛得到錯誤:

錯誤[E0423]:期望值,找到結構Kind -> src / main.rs:17:24

  | 17 | "kind" => Kind, | ^^^^ did you mean `Kind { /* fields */ }`? 

錯誤[E0423]:期望值,找到結構Location -> src / main.rs:18:24

  | 18 | "location" => Location | ^^^^^^^^ did you mean `Location { /* fields */ >}`? 

impl Component作為返回類型基本上是T where T: Component ,其中T由函數本身而不是調用方選擇。

T可以是KindT可以是Location ,但T不能同時是兩者。

兩種解決方案:

  1. 動態地:返回Box<dyn Component>並返回Box::new(Kind{})Box::new(Location{}) 缺點是它會導致堆分配。

  2. 靜態地,通過返回一個enum

enum KindOrLocation {
    Kind(Kind),
    Location(Location),
}

要使其可用作Component ,可以實現Deref<Target = dyn Component>

impl Deref for KindOrLocation {
    type Target = dyn Component + 'static;
    fn deref(&self) -> &Self::Target {
        match self {
            KindOrLocation::Kind(x) => x,
            KindOrLocation::Location(x) => x,
        }
    }
}

這里的缺點是您必須編寫此樣板代碼。


順便說說:

  • 如果您使用{}定義一個結構,例如struct Kind {} ,則可以通過編寫Kind{}創建對象,而不僅僅是Kind
  • 您需要在比賽中處理_情況: _ => panic!()
  • 不要使用&String ,而應使用&str 然后,它同時適用於&String&str

編譯器必須知道在編譯時要在堆棧上保留多少空間。 如鏈接的答案所述,如果具體的返回類型是有條件的,則直到運行時才能知道所需的空間量。 這就是答案的含義:

它的確有局限性,例如,當具體的返回類型是有條件的時,就不能使用它。 在這種情況下,您需要使用以下特征對象答案。

如果要有條件地返回KindLocation則應使用該答案中顯示的函數的第二種形式。 在這種情況下,將在堆而不是堆棧上創建KindLocation 堆棧將包含一個Box擁有該堆參考,和Box是一個類型,其尺寸在編譯時是已知的。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM