繁体   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