有没有办法提取枚举中的元素数量?
简单的例子(用虚构的number_of_elements方法):
enum FooBar { A = 0, B, C, };
println!("Number of items: {}", FooBar.number_of_elements());
// "Number of items: 3"
Run Code Online (Sandbox Code Playgroud)
在C中,我通常会......
enum FooBar { A = 0, B, C, };
#define FOOBAR_NUMBER_OF_ITEMS (C + 1)
Run Code Online (Sandbox Code Playgroud)
但是相当于Rust的Rust不起作用:
enum FooBar { A = 0, B, C, };
const FOOBAR_NUMBER_OF_ITEMS: usize = (C as usize) + 1;
// Raises an error:
// unimplemented constant expression: enum variants
Run Code Online (Sandbox Code Playgroud)
包括枚举中的最后一项是非常不方便的,因为如果不考虑所有成员,匹配的枚举将会出错.
enum FooBar { A = 0, B, C, FOOBAR_NUMBER_OF_ITEMS, };
Run Code Online (Sandbox Code Playgroud)
有没有办法将枚举中的项目数作为常量值?
注意:即使这与问题没有直接关系,我之所以想要这个功能,是因为我正在使用构建器模式构建一系列只运行一次的操作.出于这个原因,我可以使用枚举大小的固定大小的数组.
ane*_*ees 20
rust nightly版本中有一个新函数std::mem::variant_count。
Rust 文档使用的示例。
use std::mem;
enum Void {}
enum Foo { A(&'static str), B(i32), C(i32) }
assert_eq!(mem::variant_count::<Void>(), 0);
assert_eq!(mem::variant_count::<Foo>(), 3);
assert_eq!(mem::variant_count::<Option<!>>(), 2);
assert_eq!(mem::variant_count::<Result<!, !>>(), 2);
Run Code Online (Sandbox Code Playgroud)
oli*_*obk 11
您可以使用新的程序宏(在撰写本答案之日起2周内稳定):
extern crate proc_macro;
extern crate syn;
#[macro_use]
extern crate quote;
use proc_macro::TokenStream;
#[proc_macro_derive(EnumVariantCount)]
pub fn derive_enum_variant_count(input: TokenStream) -> TokenStream {
let syn_item: syn::DeriveInput = syn::parse(input).unwrap();
let len = match syn_item.data {
syn::Data::Enum(enum_item) => enum_item.variants.len(),
_ => panic!("EnumVariantCount only works on Enums"),
};
let expanded =quote! {
const LENGTH: usize = #len;
};
expanded.into()
}
Run Code Online (Sandbox Code Playgroud)
它留给读者一个练习,以确保这个派生宏可以在同一个模块中多次使用.
要使用宏,只需附加#[derive(EnumVariantCount)]到您的枚举.现在应该有一个名为的全局常量LENGTH.
Noc*_*ker 10
作为替代方案(也许这是自原始答案以来更新的),您可以使用strum crate 并使用 EnumCount 宏。这是他们的例子:
use strum::{EnumCount, IntoEnumIterator};
use strum_macros::{EnumCount as EnumCountMacro, EnumIter};
#[derive(Debug, EnumCountMacro, EnumIter)]
enum Week {
Sunday,
Monday,
Tuesday,
Wednesday,
Thursday,
Friday,
Saturday,
}
assert_eq!(7, Week::COUNT);
assert_eq!(Week::iter().count(), Week::COUNT);
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
2877 次 |
| 最近记录: |