rust 编写一个宏来遍历枚举的所有值并创建一个常量

ttp71kqs  于 2023-10-20  发布在  其他
关注(0)|答案(2)|浏览(140)

我有一个enum,我也想在match语句中使用它作为const。我正在尝试创建一个如下所示的宏:

#[macro_export]
macro_rules! enum_consts {
    ($name:ident) => {
        // Use the iter method to get the iterator
        for variant in $name::iter() {
            // Use paste to create identifiers from literals
            paste::paste! {
                // Declare a const for each variant
                const [< $name _ $variant >]: u8 = variant as u8;
            }
        }
    };
}

enum Color {
    Red,
    Green
}

enum_consts!{ Color }

然而,我在宏中迭代枚举时遇到了以下错误:

error: macro expansion ignores token `for` and any following
 --> abc.rs:1951:9
     |
1951 |         for variant in $name::iter() {
     |         ^^^

如何解决这个问题?

h7wcgrx3

h7wcgrx31#

我认为这是一个XY问题,因为枚举条目已经是一种const
在您的示例中,值Color::RedColor::Green是可以在const上下文中使用的两个值;因此我认为它们已经是const类了。我看不出将它们分别声明为const值有什么好处。
我有一个enum,我也想在match语句中使用它作为const
match语句中使用这些值已经是可能的。事实上,这是预期的方式:

pub enum Color {
    Red,
    Green,
}

fn main() {
    let color = Color::Red;

    match color {
        Color::Red => println!("Red!"),
        Color::Green => println!("Green!"),
    }
}
Red!

如果你绝对不喜欢值前面的Color::,你可以在某个地方使用use Color::*;尽管这通常被视为反模式,因为它增加了名称冲突的可能性。
例如,你可以这样做:

pub enum Color {
    Red,
    Green,
}

use Color::*;

fn main() {
    let color = Red;

    match color {
        Red => println!("Red!"),
        Green => println!("Green!"),
    }
}
Red!

如果这样做了(在我所知道的实际代码库中),那么它通常只在本地范围内这样做:

pub enum Color {
    Red,
    Green,
}

fn main() {
    use Color::*;

    let color = Red;

    match color {
        Red => println!("Red!"),
        Green => println!("Green!"),
    }
}
Red!
ikfrs5lh

ikfrs5lh2#

虽然我不确定你想解决什么问题,但你可以从每个枚举变量创建一个常量,如下所示:

use paste::paste;

macro_rules! color_consts{
    {
        $(#[$($attr:tt)*])*
        $vis:vis enum $name:ident {
            $($variant:ident,)* 
        }
    } => {
        $(#[$($attr)*])*
        $vis enum $name { $($variant,)* }
        
        $(paste!{const [<$name _ $variant>]:$name = $name::$variant; } )*
    }
}

color_consts! {
    enum Color {
        Red,
        Green,
        Blue,
    }
}

这将产生:

enum Color { Red, Green, Blue, }
const Color_Red: Color = Color::Red;
const Color_Green: Color = Color::Green;
const Color_Blue: Color = Color::Blue;

不过,我不确定这有什么潜在用途。

相关问题