Struct::new
沒有任何依賴於F
的參數,所以編譯器無法推斷它應該用於F
的類型。如果以後調用了使用F
的方法,那麼編譯器將使用該信息來計算Struct
的具體類型。例如:
use std::hash::Hash;
use std::collections::HashMap;
pub struct Struct<T, F>
where T: Eq,
T: Hash,
F: Fn() -> T,
{
hash_map: HashMap<T, F>,
value: T,
}
impl<T, F> Struct<T, F>
where T: Eq,
T: Hash,
F: Fn() -> T,
{
pub fn new(init_value: T) -> Struct<T, F> {
Struct {
hash_map: HashMap::new(),
value: init_value,
}
}
pub fn set_fn(&mut self, value: T, func: F) {
self.hash_map.insert(value, func);
}
}
fn main() {
let mut a = Struct::new(0);
a.set_fn(0, || 1); // the closure here provides the type for `F`
}
雖然這存在問題。如果我們調用set_fn
第二次用不同的封閉:
fn main() {
let mut a = Struct::new(0);
a.set_fn(0, || 1);
a.set_fn(1, || 2);
}
那麼我們得到一個編譯錯誤:
error[E0308]: mismatched types
--> <anon>:33:17
|
33 | a.set_fn(1, || 2);
| ^^^^ expected closure, found a different closure
|
= note: expected type `[[email protected]<anon>:32:17: 32:21]`
= note: found type `[[email protected]<anon>:33:17: 33:21]`
note: no two closures, even if identical, have the same type
--> <anon>:33:17
|
33 | a.set_fn(1, || 2);
| ^^^^
help: consider boxing your closure and/or using it as a trait object
--> <anon>:33:17
|
33 | a.set_fn(1, || 2);
| ^^^^
由於編譯器所提到的,每個封閉表達式定義一個全新的類型,計算結果爲那種類型。但是,通過定義Struct
的方式,可以強制HashMap
中的所有函數具有相同的類型。那真的是你想要的嗎?
如果您想將T
的不同值映射到可能不同類型的閉包,那麼您需要使用trait對象而不是泛型,正如編譯器所建議的那樣。如果你想讓結構擁有閉包,那麼你必須圍繞對象類型使用Box
。
pub struct Struct<T>
where T: Eq,
T: Hash,
{
hash_map: HashMap<T, Box<Fn() -> T + 'static>>,
value: T,
}
set_fn
然後可能看起來像這樣:
pub fn set_fn<F: Fn() -> T + 'static>(&mut self, value: T, func: F) {
self.hash_map.insert(value, Box::new(func));
}
謝謝!這確實解決了我的問題。我不明白'T +'靜態'語法。這是什麼(所以我可以閱讀適當的文檔)?這是關於一生的嗎? – pLesur
這裏''static'是一個_lifetime bound_。它限制了實現'Fn() - > T'的類型中借用指針的生存期。 ''static'意味着這個類型不能包含任何短於''static'的借入指針(一個沒有借用指針的類型是OK的)。如果你需要更多的靈活性,你可以在'Struct'上引入一個生命週期參數('<'a, T>')並用它來代替。 –