2015-10-18 13 views
4

我有此代碼(做作和純粹的實驗)「不明確關聯的類型」返回一個通用的λ時

fn math_op(op: &str) -> Option<Box<Fn(i32, i32) -> i32>> { 
    let ret: Option<Box<Fn(i32, i32) -> i32>> = match op { 
     "+" => Some(Box::new(|a: i32, b: i32| -> i32 { a + b })), 
     "-" => Some(Box::new(|a: i32, b: i32| -> i32 { a - b })), 
     "*" => Some(Box::new(|a: i32, b: i32| -> i32 { a * b })), 
     "/" => Some(Box::new(|a: i32, b: i32| -> i32 { a/b })), 
     _ => None, 
    }; 

    ret 
} 

它返回一個函數/λ取兩個操作數並返回結果(在這種情況下,添加,減法,除法和乘法運算符)

可以稱之爲像這樣:

let add: Option<Box<Fn(i32, i32) -> i32>> = math_op("+"); 
println!("Add {}", add.unwrap()(10, 2)); 

我真的很想做這個仿製藥,所以到目前爲止,我有...

fn math_op_gen<T>(op: &str) -> Option<Box<Fn(T, T) -> T::Output>> 
    where T: std::ops::Add + std::ops::Sub + std::ops::Mul + std::ops::Div { 
     let ret: Option<Box<Fn(T, T) -> T::Output>> = match op { 
      "+" => Some(Box::new(|a, b| { a + b })), 
      "-" => Some(Box::new(|a, b| { a - b })), 
      "*" => Some(Box::new(|a, b| { a * b })), 
      "/" => Some(Box::new(|a, b| { a/b })), 
      _ => None, 
     }; 

     ret 
} 

但是,當我建我得到這些錯誤:

error: ambiguous associated type `Output` in bounds of `T` [E0221] 
note: associated type `T` could derive from `core::ops::Div` 
note: associated type `T` could derive from `core::ops::Mul` 
note: associated type `T` could derive from `core::ops::Sub` 
note: associated type `T` could derive from `core::ops::Add` 

我理解,這是因爲編譯器不能確定T ::輸出從已實施的各種特質是什麼類型。有沒有另外一種方式來編寫它以使其起作用?

回答

4

您需要的輸出類型AddSubMulDiv是相同的。您可以通過添加另一個類型參數並將每個特徵的Output限制爲此類型參數來強制執行此操作。

fn math_op_gen<T, R>(op: &str) -> Option<Box<Fn(T, T) -> R>> 
    where T: std::ops::Add<Output=R> + 
      std::ops::Sub<Output=R> + 
      std::ops::Mul<Output=R> + 
      std::ops::Div<Output=R> { 
     let ret: Option<Box<Fn(T, T) -> R>> = match op { 
      "+" => Some(Box::new(|a, b| { a + b })), 
      "-" => Some(Box::new(|a, b| { a - b })), 
      "*" => Some(Box::new(|a, b| { a * b })), 
      "/" => Some(Box::new(|a, b| { a/b })), 
      _ => None, 
     }; 

     ret 
}