[英]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
可以是Kind
, T
可以是Location
,但T
不能同时是两者。
两种解决方案:
动态地:返回Box<dyn Component>
并返回Box::new(Kind{})
或Box::new(Location{})
。 缺点是它会导致堆分配。
静态地,通过返回一个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
。 编译器必须知道在编译时要在堆栈上保留多少空间。 如链接的答案所述,如果具体的返回类型是有条件的,则直到运行时才能知道所需的空间量。 这就是答案的含义:
它的确有局限性,例如,当具体的返回类型是有条件的时,就不能使用它。 在这种情况下,您需要使用以下特征对象答案。
如果要有条件地返回Kind
或Location
则应使用该答案中显示的函数的第二种形式。 在这种情况下,将在堆而不是堆栈上创建Kind
或Location
。 堆栈将包含一个Box
拥有该堆参考,和Box
是一个类型,其尺寸在编译时是已知的。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.