2017-05-22 81 views
0
enum T { 
    A(i32), 
    B(i32), 
    C(i32), 
    D(i32), 
} 

macro_rules! gen_match { 
    ($message:ident, [$(($Variant:ident, $F:ident)),*]) => { 
     match *$message { 
      $($Variant(ref x) => { 
       match *x { 
        Ok(ref a) => { 
         self.$F(a) 
        }, 
        Err(ref err) => return Err(err.clone()) 
       } 
      },)* 
      _ => {} 
     } 
    } 
} 

impl T { 
    fn test(&mut self, message: &T) -> Result<()> { 
     use self::T::*; 

     gen_match!(message, [(A, handle_a), (B, handle_b), (C, handle_c)]); 
     Ok(()) 
    } 
} 

fn main() {} 

以上不工作:如何在宏中調用self方法?

Compiling playground v0.0.1 (file:///playground) 
error[E0424]: expected value, found module `self` 
    --> src/main.rs:14:25 
    | 
14 |       self.$F(a) 
    |       ^^^^ `self` value is only available in methods with `self` parameter 
... 
28 |   gen_match!(message, [(A, handle_a), (B, handle_b), (C, handle_c)]); 
    |   ------------------------------------------------------------------- in this macro invocation 

error[E0424]: expected value, found module `self` 
    --> src/main.rs:14:25 
    | 
14 |       self.$F(a) 
    |       ^^^^ `self` value is only available in methods with `self` parameter 
... 
28 |   gen_match!(message, [(A, handle_a), (B, handle_b), (C, handle_c)]); 
    |   ------------------------------------------------------------------- in this macro invocation 

error[E0424]: expected value, found module `self` 
    --> src/main.rs:14:25 
    | 
14 |       self.$F(a) 
    |       ^^^^ `self` value is only available in methods with `self` parameter 
... 
28 |   gen_match!(message, [(A, handle_a), (B, handle_b), (C, handle_c)]); 
    |   ------------------------------------------------------------------- in this macro invocation 

error[E0243]: wrong number of type arguments: expected 2, found 1 
    --> src/main.rs:25:40 
    | 
25 |  fn test(&mut self, message: &T) -> Result<()> { 
    |          ^^^^^^^^^^ expected 2 type arguments 

我希望宏來生成

 match *message { 
      A(ref x) => { 
       match *x { 
        Ok(ref a) => { 
         self.handle_a(a) 
        }, 
        Err(ref err) => return Err(err.clone()) 
       } 
      }, 
      B(ref x) => { 
       match *x { 
        Ok(ref a) => { 
         self.handle_b(a) 
        }, 
        Err(ref err) => return Err(err.clone()) 
       } 
      }, 
      //... 
      _ => {} 
     } 

這可能嗎?我應該通過self進入宏,否則宏不能解決self

我每晚使用rustc 1.19.0。

+1

如果'gen_match'僅由'test'使用,你可以移動''macro_rules裏面的功能! – kennytm

回答

7

當出現編程問題時,它對於生成Minimal, Complete, Verifiable Example (MCVE)非常有幫助(對於問題提問者和問題回答者)。

例如,這可能已被簡化爲:

macro_rules! gen_match { 
    ($F:ident) => { 
     self.$F() 
    } 
} 

struct F; 
impl F { 
    fn dummy(&self) {} 
    fn test(&self) { 
     gen_match!(dummy); 
    } 
} 

fn main() {} 

更簡單,更容易看出問題所在:它無關匹配;只需使用特殊關鍵字/標識self即可。

爲了解決它,你可以在self傳遞給宏:

macro_rules! gen_match { 
    ($self:ident, $F:ident) => { 
     $self.$F() 
    } 
} 

struct F; 
impl F { 
    fn dummy(&self) {} 
    fn test(&self) { 
     gen_match!(self, dummy); 
    } 
} 
相關問題