[英]Rust won't let me return an instance of a type from a match, keeps thinking I'm trying to return a value
According to this answer to this questions I need to do the following to return an instance of a Trait
: 根据这个答案到这个问题 ,我需要做下面的返回一个实例Trait
:
trait Shader {}
struct MyShader;
impl Shader for MyShader {}
struct GraphicsContext;
impl GraphicsContext {
fn create_shader(&self) -> impl Shader {
let shader = MyShader;
shader
}
}
but when I try to do it: 但是当我尝试这样做时:
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
}
}
I just get errors: 我刚得到错误:
error[E0423]: expected value, found struct
Kind
--> src/main.rs:17:24 错误[E0423]:期望值,找到结构Kind
-> src / main.rs:17:24| 17 | "kind" => Kind, | ^^^^ did you mean `Kind { /* fields */ }`?
error[E0423]: expected value, found struct
Location
--> src/main.rs:18:24 错误[E0423]:期望值,找到结构Location
-> src / main.rs:18:24| 18 | "location" => Location | ^^^^^^^^ did you mean `Location { /* fields */ >}`?
That impl Component
as the return type is basically a T where T: Component
, where the T
is chosen by the function itself rather than by the caller. impl Component
作为返回类型基本上是T where T: Component
,其中T
由函数本身而不是调用方选择。
T
can be Kind
, T
can be Location
, but T
can't be both at once. T
可以是Kind
, T
可以是Location
,但T
不能同时是两者。
Two solutions: 两种解决方案:
Dynamically: Return a Box<dyn Component>
and return Box::new(Kind{})
or Box::new(Location{})
. 动态地:返回Box<dyn Component>
并返回Box::new(Kind{})
或Box::new(Location{})
。 The disadvantage is that it causes an heap allocation. 缺点是它会导致堆分配。
Statically, by returning an enum
: 静态地,通过返回一个enum
:
enum KindOrLocation {
Kind(Kind),
Location(Location),
}
To make this usable as a Component
, you can implement Deref<Target = dyn Component>
: 要使其可用作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,
}
}
}
The disadvantage here is that you have to write this boilerplate code. 这里的缺点是您必须编写此样板代码。
By the way: 顺便说说:
{}
like struct Kind {}
, you create an object of it by writing Kind{}
, not just Kind
. 如果您使用{}
定义一个结构,例如struct Kind {}
,则可以通过编写Kind{}
创建对象,而不仅仅是Kind
。 _
case in your match: _ => panic!()
or something. 您需要在比赛中处理_
情况: _ => panic!()
。 &String
, but take a &str
instead. 不要使用&String
,而应使用&str
。 Then it works for both &String
and &str
. 然后,它同时适用于&String
并&str
。 The compiler has to know how much room to reserve on the stack at compile time. 编译器必须知道在编译时要在堆栈上保留多少空间。 As the linked answer mentions, if the concrete return type is conditional, the amount of space that would be needed cannot be known until runtime. 如链接的答案所述,如果具体的返回类型是有条件的,则直到运行时才能知道所需的空间量。 That's what this bit of the answer is referring to: 这就是答案的含义:
It does have limitations, such as [...] it cannot be used when the concrete return type is conditional. 它的确有局限性,例如,当具体的返回类型是有条件的时,就不能使用它。 In those cases, you need to use the trait object answer below. 在这种情况下,您需要使用以下特征对象答案。
You should use the second form of the function shown in that answer if you want to conditionally return either a Kind
or a Location
. 如果要有条件地返回Kind
或Location
则应使用该答案中显示的函数的第二种形式。 In that case, the Kind
or the Location
will be created on the heap instead of the stack; 在这种情况下,将在堆而不是堆栈上创建Kind
或Location
。 the stack will contain a Box
that owns that heap reference, and Box
is a type whose size is known at compile time. 堆栈将包含一个Box
拥有该堆参考,和Box
是一个类型,其尺寸在编译时是已知的。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.