Rust 使用模式匹配在结构字段之间进行选择

Rust 使用模式匹配在结构字段之间进行选择,rust,Rust,背景: 我正在尝试在Rust中实现一个简单的虚拟机。现在,我正在开发一个寄存器库,它支持字符串和整数的空间。 RegisterBank结构如下所示: pub struct RegisterBank { int_registers: Vec<i32>, str_registers: Vec<String>, } 还有我想学的模式匹配 pub fn load(self, register: SomeMatchableType) { match reg

背景:

我正在尝试在Rust中实现一个简单的虚拟机。现在,我正在开发一个寄存器库,它支持字符串和整数的空间。 RegisterBank结构如下所示:

pub struct RegisterBank {
    int_registers: Vec<i32>,
    str_registers: Vec<String>,
}
还有我想学的模式匹配

pub fn load(self, register: SomeMatchableType) {
    match register { ... }
}
因为为两个非常相似的任务使用一个函数似乎很好,所以我尝试了以下方法:

enum OperandType {
    Number(i32),
    Word(String),
}
fn main() {
    let mut rb = RegisterBank::new();
    rb.store(2, 5);
    rb.store(2, "foo".to_owned());
    let intreg: i32 = rb.load(2);
    let strreg: String = rb.load(2);
    assert!(intreg == 5);
    assert!(strreg == "foo");
}
然后有一个类似于pub-fn-loadself,register:operantype的函数,它匹配register并返回一个字符串或&str,根据其操作数类型返回任意值或整数

问题: 目前,i32和String的实现停留在两个独立的函数上,这很好。因为我已经为fn-store&mut-self、register:usize、value:operantype完成了这项工作,所以对于fn-loadself、register:?,这应该是可能的???也我最大的问题是设计这样一个函数,该函数根据操作数类型枚举或其他(如果有人有聪明的想法)将两个任务组合成一个模式匹配

基本上,解决方案应该做到:

根据输入参数确定要选择的寄存器int\U寄存器或str\U寄存器 获取寄存器的内容 还它 加载模式不可能匹配输入参数,因为按照定义,它根本没有可以匹配的模式。您似乎真正在寻找的是一种通过返回类型使load成为泛型的方法——您很幸运,因为生锈实际上使这成为可能

在casei32和String中,您需要创建一个泛型特征,并为所涵盖的类型提供实现:

类似的技术可以用来摆脱笨重的操作数类型包装器。定义一个StoreRegister特性,该特性为RegisterBank提供存储,并使用i32和字符串值类型执行具体存储:

trait StoreToRegister<T> {
    fn store(&mut self, register: usize, value: T);
}

impl StoreToRegister<i32> for RegisterBank {
    fn store(&mut self, register: usize, n: i32) {
        self.int_registers[register] = n;
    }
}

impl StoreToRegister<String> for RegisterBank {
    fn store(&mut self, register: usize, s: String) {
        self.str_registers[register] = s;
    }
}

这两个特性可以合并为一个寄存器存储特性,该特性同时提供加载和保存。完整的代码。

您可以创建一个枚举注册表类型{numberUser Size,Wordusize}顺便说一句,这与您的问题没有任何关系,但我认为如果您将操作数类型重命名为仅操作数,您的代码可能会看起来更地道
let intreg: i32 = rb.load(2);  // or, let intreg = rb.load::<i32>(2);
let strreg: String = rb.load(2);
trait StoreToRegister<T> {
    fn store(&mut self, register: usize, value: T);
}

impl StoreToRegister<i32> for RegisterBank {
    fn store(&mut self, register: usize, n: i32) {
        self.int_registers[register] = n;
    }
}

impl StoreToRegister<String> for RegisterBank {
    fn store(&mut self, register: usize, s: String) {
        self.str_registers[register] = s;
    }
}
fn main() {
    let mut rb = RegisterBank::new();
    rb.store(2, 5);
    rb.store(2, "foo".to_owned());
    let intreg: i32 = rb.load(2);
    let strreg: String = rb.load(2);
    assert!(intreg == 5);
    assert!(strreg == "foo");
}