Macros 是否可以定义一个宏,从数字生成所有枚举值的静态数组?
我想写这段代码:Macros 是否可以定义一个宏,从数字生成所有枚举值的静态数组?,macros,rust,Macros,Rust,我想写这段代码: enum Foo { A1 = 1, A17 = 17, A42 = 42, } static FOO_VALUES: [Foo; 3] = [Foo::A1, Foo::A17, Foo::A42]; impl Foo { fn to_num(self) -> i32 { match self { Foo::A1 => 1, //... }
enum Foo {
A1 = 1,
A17 = 17,
A42 = 42,
}
static FOO_VALUES: [Foo; 3] = [Foo::A1, Foo::A17, Foo::A42];
impl Foo {
fn to_num(self) -> i32 {
match self {
Foo::A1 => 1,
//...
}
fn from_num(a: i32) -> Result<Foo, ()> {
//...
}
}
}
宏的用法类似于define\u foo\u enum!(1, 17, 42);代码>
我想这段代码不会编译,因为concat\ident代码>无法以我尝试使用它的方式工作。此外,我正在为宏提供数字,而不是标识符,但我不知道使用什么类型,tt
我使用的是Rust 1.17。我的板条箱可以像您预期的那样形成串联标识符。自1.15以来,它支持任何稳定的Rust编译器,尽管在下面的实现中,我使用了一个需要Rust 1.20+的相关常量
#[macro_use]
extern crate mashup;
macro_rules! define_foo_enum {
($name:ident { $($number:tt),* }) => {
mashup! {
$(
m["A" $number] = A $number;
)*
}
m! {
#[derive(Debug, PartialEq)]
pub enum $name {
$(
"A" $number,
)*
}
impl $name {
pub const VALUES: &'static [Self] = &[$($name::"A" $number,)*];
}
}
}
}
define_foo_enum!(Foo { 1, 17, 42 });
fn main() {
assert_eq!(Foo::VALUES, [Foo::A1, Foo::A17, Foo::A42]);
}
注意:to_num(self)
可以写成self as i32
。显然,反向转换并不容易,因为并非所有整数都是有效值。此外,您还可以使用#[repr(i32)]
强制编译器了解Foo
在内存中的表示方式,从而允许transmute
用于反向转换。@MatthieuM。事实上,主要功能是所有值的数组(ITEMS
),从/到i32并不重要,至少mactch
和rustc
可以控制我在匹配中提到所有值,但手工定义的数组只能有几个匹配值,编译器对此不作任何报告。@user1244932您的意思是concat_idents代码>@肯尼特:我需要像concat\n这样的东西代码>,不完全是它
#[macro_use]
extern crate mashup;
macro_rules! define_foo_enum {
($name:ident { $($number:tt),* }) => {
mashup! {
$(
m["A" $number] = A $number;
)*
}
m! {
#[derive(Debug, PartialEq)]
pub enum $name {
$(
"A" $number,
)*
}
impl $name {
pub const VALUES: &'static [Self] = &[$($name::"A" $number,)*];
}
}
}
}
define_foo_enum!(Foo { 1, 17, 42 });
fn main() {
assert_eq!(Foo::VALUES, [Foo::A1, Foo::A17, Foo::A42]);
}