How to get the number of elements (variants) in an

2019-06-15 23:37发布

Is there a way to extract the number of elements in an enum?

Simple example (with imaginary number_of_elements method):

enum FooBar { A = 0, B, C, };

println!("Number of items: {}", FooBar.number_of_elements());
// "Number of items: 3"

In C I'd normally do...

enum FooBar { A = 0, B, C, };
#define FOOBAR_NUMBER_OF_ITEMS (C + 1)

However the Rust equivalent to this doesn't work:

enum FooBar { A = 0, B, C, };
const FOOBAR_NUMBER_OF_ITEMS: usize = (C as usize) + 1;

// Raises an error:
//     unimplemented constant expression: enum variants

Including the last item in the enum is very inconvenient because matching enums will error if all members aren't accounted for.

enum FooBar { A = 0, B, C, FOOBAR_NUMBER_OF_ITEMS, };

Is there a way to get the number of items in an enum as a constant value?


Note: even though this isn't directly related to the question, the reason I was wanting this feature is I'm using the builder-pattern to construct a series of actions which only make sense to run once. For this reason I can use a fixed size array the size of the enum.

标签: enums rust
1条回答
劳资没心,怎么记你
2楼-- · 2019-06-16 00:08

You can use the new procedural macros (stable in 2 weeks at the date of writing this answer):

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()
}

It is left as an excercise to the reader to ensure that this derive macro can be used multiple times within the same module.

To use the macro, just attach #[derive(EnumVariantCount)] to your enum. There should now be a global constant named LENGTH.

查看更多
登录 后发表回答