2015-04-03 83 views
2

我有一個通用結構,我想存儲一個閉包。這個閉包的參數和返回類型直接關係到結構的最終類型。我怎樣才能定義這樣的結構?泛型閉包如何存儲在泛型結構中?

我知道如何使用關鍵字where複合類型的唯一方法。但是,當試圖編譯代碼時,編譯器會暫停並抱怨T't未被使用。

我可以通過添加使用T't的無用變量來編譯它,但我認爲有一個更好,更正確的爲什麼要這樣做。

以下代碼(playpen編譯。刪除無用的變量,它不會:

pub struct GenericContainer<'t, T: 't, F> where F: Fn(&'t [T]) -> Option<&'t [T]> { 
    generic_closure: F, 
    unused: Option<&'t T> 
} 

impl<'t, T: 't, F> GenericContainer<'t, T, F> where 
    F: Fn(&'t [T]) -> Option<&'t [T]> { 

    pub fn new(gc: F) -> Self { 
     GenericContainer { 
      generic_closure: gc, 
      unused: None 
     } 
    } 

    pub fn execute(&self, slice: &'t [T]) -> Option<&'t [T]> { 
     let g = &self.generic_closure; 
     let _ = &self.unused; 
     g(slice) 
    } 
} 

fn main() { 
    let g = GenericContainer::new(|s| if s.len() == 0 {None} else {Some(&s[..1])}); 
    assert!(g.execute(b" ") == Some(b" ")); 
    println!("ok"); 
} 
+0

友好的音符誰可能有誤也徘徊在這條道路的人:確保你真的* *要使用閉包這種方式。通常,使用正常的struct + traits路徑將完成你想要做的事情,並且不會導致唯一類型的結構。 – urubi 2015-04-04 06:28:09

回答

3

你是一個典型的「排名高的東西」的局面:'tT僅用於定義類型F

首先,對於壽命,可以使用鏽的較高排名-壽命語法:

where F: for<'t> Fn(&'t [T]) -> Option<&'t [T]> 

並因此從你結構類型中刪除。

T做類似的事情會很好,但排名較高的類型目前不被Rust支持。所以,你最好的缺點是可能跟隨編譯器的建議,並使用std::maker::PhantomData

你最終像類型:

pub struct GenericContainer<T, F> 
    where F: for<'t> Fn(&'t [T]) -> Option<&'t [T]> 
{ 
    generic_closure: F, 
    _marker: ::std::marker::PhantomData<T> 
} 

注意前綴_marker_防止它被作爲閒置檢測。

然後,您只需要更新您的實現:

impl<T, F> GenericContainer<T, F> where 
    F: for<'t> Fn(&'t [T]) -> Option<&'t [T]> { 

    pub fn new(gc: F) -> Self { 
     GenericContainer { 
      generic_closure: gc, 
      _marker: ::std::marker::PhantomData 
     } 
    } 

    pub fn execute<'t>(&self, slice: &'t [T]) -> Option<&'t [T]> { 
     let g = &self.generic_closure; 
     g(slice) 
    } 
}