2016-11-13 11 views
5

マクロで実装を定義する場合、構造体メンバ型にアクセスして余分な引数として渡す必要がないようにすると便利です。それはどのタイプの事前に知らなくても、構造体のメンバの種類にアクセスする方法はあり関数シグネチャや宣言のための構造体メンバの型にアクセスすることは可能ですか?

impl PartialEq<u32> for MyStruct { ... } 

this questionを参照してください)?

​​

場合、それは便利です、これは私がこれを行うに興味がある理由の省略例です。

struct_bitflag_impl!(
    pub struct MyFlag(u8);, 
    MyFlag, u8); 

//   ^^ how to avoid having this extra arg? 
//    (Used by ``impl PartialEq<$t_internal> for $p``) 
//    couldn't it be discovered from `MyFlag.0` ? 

// the macro 

macro_rules! struct_bitflag_impl { 
    ($struct_p_def: item, $p:ident, $t_internal:ty) => { 

     #[derive(PartialEq, Eq, Copy, Clone, Debug)] 
     $struct_p_def 

     impl ::std::ops::BitAnd for $p { 
      type Output = $p; 
      fn bitand(self, _rhs: $p) -> $p { $p(self.0 & _rhs.0) } 
     } 
     impl ::std::ops::BitOr for $p { 
      type Output = $p; 
      fn bitor(self, _rhs: $p) -> $p { $p(self.0 | _rhs.0) } 
     } 
     impl ::std::ops::BitXor for $p { 
      type Output = $p; 
      fn bitxor(self, _rhs: $p) -> $p { $p(self.0^_rhs.0) } 
     } 

     impl ::std::ops::Not for $p { 
      type Output = $p; 
      fn not(self) -> $p { $p(!self.0) } 
     } 

     // support comparison with the base-type. 
     impl PartialEq<$t_internal> for $p { 
      fn eq(&self, other: &t_internal) -> bool { 
       self.0 == *other 
      } 
     } 
     // ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ 
     //  How to avoid using 't_internal' here? 
    } 
} 
+0

@keeprからのコメント、これは 'custom_derive'によって処理される可能性があります:https://docs.rs/custom_derive/*/custom_derive/index.html – ideasman42

答えて

4

いいえ、型位置にない使用することができ、一般的なtypeof(Type::field)存在しない。


質問の例に関しては、特別な種類のアイテム、すなわち1つのフィールドのみを持つタプル構造が必要なようです。だから、代わりに$itemフラグメントを受け入れるのは、次の構文を自分でシミュレートすることができます

macro_rules! foo { 
    (pub struct $name:ident ($ty:ident)) => { 
     pub struct $name($ty); 

     impl $name { 
      pub fn bar() { 
       println!("{}", stringify!($ty)); 
      } 
     } 
    } 
} 

foo!(
    pub struct Peter(u8) 
); 

fn main() { 
    Peter::bar(); 
} 

あなたは一度だけ、すべてを指定する必要がその方法を。しかし、これは明らかに1種類のタプル構造体定義でのみ機能し、すべての種類の項目では機能しません。しかし、あなたのユースケースは、この特殊なケースに多かれ少なかれ興味があることを示唆しています。

異なる種類の構造体定義を許可したい場合は、異なる構文を可能にするためにマクロにさらに多くのマクロ規則を追加するだけです。例を見ると、here is code to allow for pub and non-pub tuple-struct definitionsです。しかし、これはさらに拡大する可能性があります。

+0

structと内部のメンバーですか?たとえば、 'struct Peter(pub u8)'や 'pub struct Peter(u8)'を実行したいかもしれません。 – ideasman42

+0

@ ideasman42これは、特定のケースでは非常にハードコードされています。もしあなたが 'pub'と' pub'の柔軟性を望むなら、より多くのマクロ "arms"を追加することができます...より良いバージョンを構築して質問にリンクさせてください。お待ちください;-) –

+0

マクロのこのスタイルを使用するように私のコードを更新しました。https://gitlab.com/ideasman42/bmesh-rs/blob/master/bmesh/src/bitflag_macros.rs - どのように 'Peter (u8) 'と'ピーター(pub u8) 'が行われます。 – ideasman42

関連する問題