为什么我得到“匹配武器的类型不兼容"?返回“impl Trait"的函数中的错误? [英] Why do I get a "match arms have incompatible types" error in a function returning `impl Trait`?

查看:61
本文介绍了为什么我得到“匹配武器的类型不兼容"?返回“impl Trait"的函数中的错误?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

trait Counter {
    fn count(&self) -> i32;
}

struct AddCounter {
    a: i32,
    b: i32,
}
impl Counter for AddCounter {
    fn count(&self) -> i32 {
        self.a + self.b
    }
}

struct MulCounter {
    a: i32,
    b: i32,
}
impl Counter for MulCounter {
    fn count(&self) -> i32 {
        self.a * self.b
    }
}

fn get_counter(a: i32, b: i32, op: &str) -> impl Counter {
    match op {
        "+" => AddCounter { a, b },
        "*" => MulCounter { a, b },
        _ => panic!(format!("{}{}", "未知的符号:", op)),
    }
}

fn main() {}

当我调用 get_counter(...) 时出现错误:

I get an error when I call get_counter(...):

error[E0308]: match arms have incompatible types
  --> src/main.rs:26:5
   |
26 | /     match op {
27 | |         "+" => AddCounter { a, b },
28 | |         "*" => MulCounter { a, b },
   | |                ------------------- match arm with an incompatible type
29 | |         _ => panic!(format!("{}{}", "未知的符号:", op)),
30 | |     }
   | |_____^ expected struct `AddCounter`, found struct `MulCounter`
   |
   = note: expected type `AddCounter`
              found type `MulCounter`

推荐答案

impl Trait 表示法视为泛型类型.你不能写:

See the impl Trait notation as a generic type. You cannot write:

fn get_counter<T>(a: i32, b: i32, op: &str) -> T {
    match op {
        "+" => AddCounter { a, b },
        "*" => MulCounter { a, b },
        _ => panic!(format!("{}{}", "未知的符号:", op)),
    }
}

因为AddCounterMulCounter 没有相同的类型:什么是T?

because AddCounter and MulCounter do not have the same type: what is T?

您可以使用动态分派代替静态分派:

You can use dynamic dispatch instead of static dispatch:

fn get_counter(a: i32, b: i32, op: &str) -> Box<dyn Counter> {
    match op {
        "+" => Box::new(AddCounter { a, b }),
        "*" => Box::new(MulCounter { a, b }),
        _ => panic!(format!("{}{}", "未知的符号:", op)),
    }
}

进一步说明

当您使用静态分派时,Rust 编译器会单态代码:它为泛型类型的每个值生成一个新函数(参见 什么是带有上下文的单态化到 C++? 了解更多详细信息).每个返回值都是真正的"普通类型.在这种情况下,函数不能返回(例如)一个路径中的 String 和另一个路径中的 i32.

Further explanation

When you use static dispatch, the Rust compiler monomorphizes the code: it generates a new function for each value of the generic type (see What is monomorphisation with context to C++? for more details). Each of those returned values are "real" plain types. In this case, a function cannot return (for example) a String in one path and an i32 in another path.

对于 动态调度,返回的不是真实"类型而是trait对象:编译器不知道真实类型;它只关心 trait 对象是否可以用作 trait 实现者.这就是您所需要的.

In the case of dynamic dispatch, it is not the "real" type that is returned but a trait object: the compiler does not know the real type; it only cares that the trait object can be used as a trait implementor. That is what you need here.

这篇关于为什么我得到“匹配武器的类型不兼容"?返回“impl Trait"的函数中的错误?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆