创建一个具有枚举元素大小的数组

Create an array with enum element size

我想创建一个大小由枚举中的元素指定的数组,如下所示:

pub use self::Register::*;

enum Register {
    Ip,
    Sp,
    NumRegs,
}

struct State {
    val: int,
    regs: [int; NumRegs as int],
    running: bool,
}

但我得到:

src/main.rs:19:11: 19:32 error: expected constant expr for array length: non-constant path in constant expr
src/main.rs:19     regs: [int; NumRegs as int],

我已经尝试使用 as int,以及其他解决方案,并在 Google 上搜索了一段时间,但没有找到解决方案。顺便说一句,这种形式在 Rust 中是错误的吗?

目前,我不认为 Rust 能够看到 Enum::Variant 实际上是一个常数(我实际上也不知道它 ) ,所以它不能用作数组长度。不仅如此,我想说添加一个实际上并不打算使用的枚举变体很奇怪。

对于我如何看待你的问题,我可能会尝试将你的寄存器表示为一个结构:

struct Registers {
    ip: u8,
    sp: u8,
}

struct State {
    val: u8,
    regs: Registers,
    running: bool,
}

fn main() {
    let s = State {
        val: 0,
        regs: Registers { ip: 0, sp: 0 },
        running: false,
    };
}

编辑

如果您想按姓名注册,我们直接这样做如何:

struct Registers {
    ip: u8,
    sp: u8,
}

impl Registers {
    fn by_name(&self, name: &str) -> u8 {
        match name {
            "ip" => self.ip,
            "sp" => self.sp,
            _ => panic!("Unknown register '{}'", name),
        }
    }

    fn by_name_mut(&mut self, name: &str) -> &mut u8 {
        match name {
            "ip" => &mut self.ip,
            "sp" => &mut self.sp,
            _ => panic!("Unknown register '{}'", name),
        }
    }
}

fn main() {
    let mut r = Registers { ip: 0, sp: 0 };

    println!("Instruction pointer: 0x{:02x}", r.by_name("ip"));
    *r.by_name_mut("ip") += 1;
    println!("Instruction pointer: 0x{:02x}", r.by_name("ip"));
}

虽然那里的 panic! 非常丑陋......我宁愿为此目的使用枚举。让我们同时处理枚举和字符串:

use std::str::FromStr;

#[derive(Debug,Copy,Clone,PartialEq)]
enum Register {
    Ip,
    Sp,
}

impl FromStr for Register {
    type Err = ();

    fn from_str(s: &str) -> Result<Self, ()> {
        match s {
            "ip" => Ok(Register::Ip),
            "sp" => Ok(Register::Sp),
            _ => Err(()),
        }
    }
}

struct Registers {
    ip: u8,
    sp: u8,
}

impl Registers {
    fn by_name(&self, name: Register) -> u8 {
        match name {
            Register::Ip => self.ip,
            Register::Sp => self.sp,
        }
    }

    fn by_name_mut(&mut self, name: Register) -> &mut u8 {
        match name {
            Register::Ip => &mut self.ip,
            Register::Sp => &mut self.sp,
        }
    }
}

fn main() {
    let mut rs = Registers { ip: 0, sp: 0 };

    let r: Register = "ip".parse().unwrap();

    println!("Instruction pointer: 0x{:02x}", rs.by_name(r));
    *rs.by_name_mut(r) += 1;
    println!("Instruction pointer: 0x{:02x}", rs.by_name(r));
}

现在我们在将字符串转换为我们的 Register 类型之间有了一个很好的明确区分,这意味着我们的代码只有一部分必须处理无效的寄存器名称(对 unwrap 的调用).