如何在Rust中匹配数据类型?

时间:2017-01-11 17:03:50

标签: rust

我试图匹配结构的通用字段的数据类型并做出相应的反应。我的总体想法是这样的(代码没有编译):

struct foo<T> {
    zaz: String,
    bar: T,
}

fn main() {
    let x = foo::<String> {
        zaz: "Hello".to_string(),
        bar: "world".to_string(),
    };
    let y = foo::<u32> {
        zaz: "Hello".to_string(),
        bar: 5,
    };

    match x.bar {
        String => println!("It's a string!"),
        u32 => println!("It's a u32!"),
        _ => println!("Something else"),
    };

    println!("end of program!");
}

来自rustc的错误消息:

error[E0001]: unreachable pattern
  --> src/main.rs:18:9
   |
18 |         u32 => println!("It's a u32!"),
   |         ^^^ this is an unreachable pattern
   |
note: this pattern matches any value
  --> src/main.rs:17:9
   |
17 |         String => println!("It's a string!"),
   |         ^^^^^^

error[E0001]: unreachable pattern
  --> src/main.rs:19:9
   |
19 |         _ => println!("Something else"),
   |         ^ this is an unreachable pattern
   |
note: this pattern matches any value
  --> src/main.rs:17:9
   |
17 |         String => println!("It's a string!"),
   |         ^^^^^^

我想要的是x匹配第一个,y匹配第二个。我实际上不确定我想做什么,但是能达到预期效果的是什么?

1 个答案:

答案 0 :(得分:12)

惯用解决方案

创建一个约束T中参数foo的特征,将任何特定行为实现为此特征的关联函数。

示例:

trait PrintMe {
    fn print_me(&self);
}

impl PrintMe for String {
    fn print_me(&self) { println!("I am a string"); }
}

struct Foo<T: PrintMe> {
    zaz: String,
    bar: T
}

fn main() {
    // ...
    x.bar.print_me();
}

这是原则泛型编程,您可以在其中准确声明可能的通用参数的行为差异,这样就不会有任何意外。

精确解决方案

Rust确实可以查询类型:每种类型都有一个唯一的TypeId关联,您可以在TypeId上进行一系列if检查。它很笨重。

fn print_me<T>(x: &Foo<T>) {
    if TypeId::of::<T>() == TypeId::of::<String>() {
        println!("I am a string");
    } else // ...
}

但请......不要这样做:)。