创建一个包含枚举元素大小的数组

时间:2015-01-09 17:19:59

标签: arrays enums rust

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

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以及其他解决方案,并且谷歌搜索了一段时间,但还没有找到解决方案。顺便说一句,这是Rust中的错误形式吗?

1 个答案:

答案 0 :(得分:2)

目前,我不认为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的调用)。