2016-11-03 56 views
0

如果我們想推廣將#[derive(...)]應用於一個結構體,在某些情況下,將它包含在一個宏中會很有用。是否可以在宏中嵌套結構聲明以應用結構屬性?

非工作的例子:

my_traits!(
    pub struct MyType(u32), 
    MyType 
); 

my_traits可以與#[derive(...)]前綴的第一個參數,並使用第二個參數來聲明impl SomeTrait for $t {...}

聲明實現工作沒有任何問題,但我沒有設法找到一種方法來使用宏來爲結構聲明前綴的屬性。


獲取這可以用於一個例子來看看這個問題:
Possible to derive attributes *after* a struct declaration?

回答

2

#[derive(...)]成微距似乎很好地工作:

#[derive(Eq,PartialEq,Debug)] 
struct Foo(u32); 

macro_rules! my_eq(
    ($name:ident) => { 
     #[derive(Eq,PartialEq,Debug)] 
     struct $name(u32); 
    }; 
); 

my_eq!(Bar); 

fn main() { 
    assert_eq!(Foo(3), Foo(3)); 
    assert!(Foo(3) != Foo(4)); 
    assert_eq!(Bar(3), Bar(3)); 
    assert!(Bar(3) != Bar(4)); 

} 

Playground link

或者如果你想通過struct

macro_rules! my_eq(
    ($name:item) => { 
     #[derive(Eq,PartialEq,Debug)] 
     $name 
    }; 
); 

my_eq!(struct Bar(u32);); 

Playground

注意的是,宏接受一個完整的項目,所以需要宏調用內部的分號(Foo{}結構並不需要它,寫在線時一樣)。

+0

謝謝,我可能最終會這樣做。主要的缺點是 - 儘管這樣做,我想要傳入整個聲明,否則我需要爲'pub struct $ name(u32);'和'struct $ name(pub u32);' (公共結構和公共成員)。 – ideasman42

0

這可以通過傳遞item來完成,這要歸功於IRC上的@j_ey。

macro_rules! ideas { 
    ($ty: item, $id: ident) => { 
     #[derive(Debug)] 
     $ty 
     impl $id { 
      fn doit(){} 
     } 
    } 
} 

ideas!(pub struct Foo(u32);, Foo); 

fn main() { 
    let f = Foo(1); 
    println!("{:?}", f); 
}