2016-11-13 14 views
5

Makrolardaki uygulamaları tanımlarken, ek bir argüman olarak iletmekten kaçınmak için bir yapı üyeleri türüne erişmek yararlı olabilir.İşlev imzaları veya bildirimleri için yapı üyesi türüne erişmek mümkün mü?

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

onun türünü önceden bilmeden bir yapı elemanının türü erişmek için bir yolu var mı (this question bakınız)?

durumda yararlıdır? In
impl PartialEq<typeof(MyStruct.member)> for MyStruct { ... } 

, bu bunu yapmak ilgileniyorum neden kısaltılmış örneğidir:

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'den alınan yorum, bu 'custom_derive' tarafından ele alınabilir: https://docs.rs/custom_derive/*/custom_derive/index.html – ideasman42

cevap

4

Hayır, tip konumunda kullanılabilecek bir genel typeof(Type::field) yapar mevcut değil Yalnızca tek bir alan tuple-yapı: öğenin özel bir tür bekliyoruz gibi, söz konusu örneğin İlişkin


görünüyor. Yani, bunun yerine bir $item parçasını kabul dizimini kendinizi simüle edebilirsiniz:

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

sadece bir kez her şeyi belirtmek zorunda Böylece. Bununla birlikte, bu açıkça, sadece her tür eşya için değil, bir tür tuple-yapı tanımıyla çalışır. Ancak kullanım durumunuz, yalnızca bu özel durumla ilgilendiğinize göre daha fazla ya da daha az olduğunu gösterir.

Farklı yapı tanımlarına izin vermek istiyorsanız, farklı sözdizimine izin vermek için makroya daha fazla makro kural eklemeniz yeterlidir. Bir örnek görmek için here is code to allow for pub and non-pub tuple-struct definitions. Ancak bu daha da genişletilebilir.

+0

Bu sabit kod hem yapı hem de onun iç üyesi? Örneğin, yapı Peter (pub u8) 'veya' pub yapısı Peter (u8) ' – ideasman42

+0

@ ideasman42 yapmak isteyebilirsiniz Kesinlikle, bu belirli bir durum için çok kodlanmış. Eğer 'pub' ve 'non-'pub' esnekliğini istiyorsanız, daha fazla makro "silah" ekleyebilirsiniz ... daha güzel bir versiyon oluşturmaya ve soruya bağlamaya çalışalım. Lütfen bekleyiniz ;-) –

+0

Harika, bu tarz bir makroyu kullanmak için kodumu güncelledim https://gitlab.com/ideasman42/bmesh-rs/blob/master/bmesh/src/bitflag_macros.rs - hala nasıl emin Peter? (u8) 've' Peter (pub u8) 'yapılırdı. – ideasman42

İlgili konular