2017-01-13 8 views
7

列挙型の要素の数を抽出する方法はありますか?列挙型の要素の数を定数値として取得するにはどうすればよいですか?

簡単な例(架空number_of_elements方法):Cで

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

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

私は正常に行うだろう...

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

これに錆相当が動作しないただし:

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

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

最後の項目を列挙型に含めることは、一致する列挙型がエラーになるため非常に不便ですすべてのメンバーが説明されていない場合。

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

定数値として列挙型の項目数を取得する方法はありますか?


注:これは、直接の質問に関連していないにもかかわらず、私はこの機能を望むた理由は、私は一度だけ実行しても意味が一連のアクションを構築するためにbuilder-patternを使用しています。このため、私は列挙型のサイズの固定サイズの配列を使用できます。

あなたは(この答えを書い日に2週間で安定した)新しい手続きマクロを使用することができます
+0

私はこれが役に立つと思われる機能に同意します。ちょうど興味のない:あなたはなぜ変種の数が必要ですか? –

+0

なぜこの機能をお探しですか? – ideasman42

+2

正直言って、私はCとC++でも不便です。なぜなら、自分のコードを汚染する 'switch'の中のケースを処理しなければならないからです。 CやC++では、enumを宣言するためのマクロ(黒い魔法使い...)を使用しています。これはまた、このサイズを含むいくつかの代替物を宣言しています。私はマクロもRustでも使えると思いますが、もっと良いものを望んでいます...(カスタム派生もおそらくトリックを行う可能性がありますね...) –

答えて

9

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::parse_macro_input(&input.to_string()).unwrap(); 
    let len = match syn_item.body { 
     syn::Body::Enum(variants) => variants.len(), 
     _ => panic!("Every type other than an enum has exactly 1 (one) variant, please just use that value instead of wasting CPU cycles ;)"), 
    }; 
    quote! { 
const LENGTH: usize = #len; 
    }.unwrap().parse().unwrap() 
} 

この派生マクロを使用することができることを確実にするために、読者に運動して残されています同じモジュール内で複数回

マクロを使用するには、#[derive(EnumVariantCount)]をenumに付けてください。今や、LENGTHという名前のグローバル定数が存在するはずです。

+1

恐ろしい!しかし、私は、エナール以外のボディーのようなerorrsを処理する適切な方法(今のところ)がパニックになると思います。私は[この投稿](https://cbreeden.github.io/Macros11/)にMacros 1.1を学ぶのが大好きです。 –

+0

なぜ非enumでパニックになるのですか?単一のvariant enumとtuple構造体には違いはありません。 –

+2

私はそれについて十分考えていなかったかもしれません。しかし、少なくとも* I *は、 '[EnumVariantCount]'を構造体定義に付けるとコンパイル時にエラーが発生すると予想します。 –

関連する問題