2015-01-09 3 views
0

Я хочу создать массив размера указанного элемента в перечислении, например, так:Создать массив размером перечисления элементов

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], 

Я ve попытался использовать as int, среди других решений, и Googled вокруг в течение некоторого времени, но не нашел решения. Кстати, это плохая форма в ржавчине?

+0

'enum' не семантически соответствует числовому значению, как вы могли бы ожидать, если бы вы пришли из C. Не могли бы вы объяснить немного больше о том, какой код вы действительно хотели бы иметь? – Shepmaster

ответ

2

В настоящее время я не думаю, что Руст способен видеть, что 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, 
    }; 
} 

Edit

Если вы хотите, чтобы получить реестр по имени, как насчет мы делаем это непосредственно:

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).

+0

Привет! Я пытаюсь создать массив регистров, индексируемых enum, так что я могу сделать простой обратный поиск по строке. В принципе, я не хочу ничего особенного в том, как я обращаюсь к регистру. Не уверен, что это имеет смысл. – tekknolagi

+0

Вы можете посмотреть github.com/tekknolagi/carp/tree/master/src/, если хотите. Подобный дизайн, но, возможно, более идиоматический. – tekknolagi

+0

@tekknolagi, я обновил свой ответ, чтобы показать, как использовать строки для идентификации, а затем предоставить доступ к определенному регистру. – Shepmaster

Смежные вопросы