英文:
In Rust can you associate a constant value to each enum variant and then collect those values at compile time?
问题
Here's the translated code snippet:
让我们假设我有一个枚举,并且我想以某种方式注释或关联每个变体与`&str`。例如:
```rust
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。我也不确定它是否回答了第二个问题。我还考虑了属性宏,但我不知道是否可以在编译时将这些属性收集在一起。
<details>
<summary>英文:</summary>
Let's say I have an enum, and I want to somehow annotate or associate each variant with a `&str`. E.g.:
enum MyEnum {
A, // "foo"
B(String), // "bar"
C(i32) // "baz"
}
I would also like to collect these `&str`'s into an array like
const arr:[&'static str; 3] = ["foo", "bar", "baz"];
Is there a nice way to do this automatically at compile time? Rather than having to write out the constant array separately? Perhaps with macros?
A `const fn` would answer the first part, but I believe it requires `#![feature(const_if_match)]`, and I would prefer using stable Rust if possible. I'm also not sure it answered the second part. I also considered attribute macros, but I don't know how (or whether) you can collect these attributes together at compile time.
</details>
# 答案1
**得分**: 0
您可以使用声明性宏来实现这一点:
```rust
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",
// ]
}
您只需要在单位变体(unit variants)中使用额外的一对括号。
英文:
You can achieve this with a declarative macro:
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",
// ]
}
You just need to use an extra pair of parens with unit variants.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论