在Rust中,你可以将一个常量值与每个枚举变量相关联,然后在编译时收集这些值吗?

fivyi3re  于 2023-06-23  发布在  其他
关注(0)|答案(1)|浏览(93)

假设我有一个枚举,我想以某种方式注解或关联每个变量与&str。例如:

enum MyEnum {
    A, // "foo"
    B(String), // "bar"
    C(i32) // "baz"
}

我还想将这些&str收集到一个数组中,如

const arr:[&'static str; 3] = ["foo", "bar", "baz"];

有没有一个好的方法可以在编译时自动完成这个任务?而不是必须单独写出常量数组?也许是宏?
const fn可以回答第一部分,但我相信它需要#![feature(const_if_match)],如果可能的话,我更喜欢使用稳定的Rust。我也不确定它是否回答了第二部分。我还考虑了属性宏,但我不知道如何(或是否)在编译时将这些属性收集在一起。

7gs2gvoe

7gs2gvoe1#

你可以通过一个声明性宏来实现这一点:

macro_rules! str_variants {
    { enum $enum_name:ident {
        $(
        #[str = $variant_str:literal]
        $variant_name:ident $variant_fields:tt
        ),* $(,)*
    } } => {
        enum $enum_name {
            $(
                $variant_name $variant_fields,
            )*
        }

        impl $enum_name {
            const ARR: &[&'static str] = &[
                $(
                    $variant_str,
                )*
            ];
        }
    }
}

str_variants! { enum MyEnum {
    #[str = "foo"]
    A(),
    #[str = "bar"]
    B(String),
    #[str = "baz"]
    C(i32)
} }

fn main() {
    dbg!(MyEnum::ARR);

// [src/main.rs:34] MyEnum::ARR = [
//     "foo",
//     "bar",
//     "baz",
// ]
}

您只需要使用一对额外的带有单位变体的父对。
playground

相关问题