簡體   English   中英

實現一個返回泛型的特征函數

[英]Implementing a trait function that returns generic

在下面的代碼中,名為 LimitCollection 的 trait 有一個函數,該函數返回一個實現 Iterator trait 的類型。

struct Limit {}

impl Limit {
    fn is_violated(&self) -> bool {
        todo!()
    }
}

trait LimitCollection {
    fn get_violated_limits<'a, I>(&'a self) -> I
    where
        I: Iterator<Item = &'a Limit>;
}

現在我想做一些實現特征的東西,但編譯器抱怨我返回的類型和泛型返回類型之間不匹配:“預期類型參數I ,找到 struct Filter

struct ConcreteLimitCollection {
    limits: Vec<Limit>,
}

impl LimitCollection for ConcreteLimitCollection {
    fn get_violated_limits<'a, I>(&'a self) -> I
    where
        I: Iterator<Item = &'a Limit>,
    {
        self.limits.iter().filter(Limit::is_violated)
    }
}

有沒有辦法讓這個構造工作,最好不訴諸動態分配?

通常你會使用關聯類型,在這種情況下我們會涉及到一些生命周期(我們需要一個 GAT,通用關聯類型)。 可悲的是,它所需要的還沒有穩定下來:

#![feature(generic_associated_types)]

struct Limit {}

impl Limit {
    fn is_violated(&self) -> bool {
        todo!()
    }
}

trait LimitCollection {
    type Output<'a>: Iterator<Item = &'a Limit> where Self: 'a;
    fn get_violated_limits<'a>(&'a self) -> Self::Output<'a>;
}

struct ConcreteLimitCollection {
    limits: Vec<Limit>,
}

impl LimitCollection for ConcreteLimitCollection {
    type Output<'a> = Box<dyn Iterator<Item = &'a Limit> + 'a> where Self: 'a;
    
    fn get_violated_limits<'a>(&'a self) -> Self::Output<'a> {
        Box::new(self.limits.iter().filter(|l| l.is_violated()))
    }
}

操場

免責聲明,即使您不想使用動態分配,我也使用Box<dyn Iterator<Item = &'a Limit> + 'a> ,但在這種情況下,您只需滿足整個Filter<...>類型. 只是為了示例的簡單性而使用了 Boxed 迭代器。

@SvenMarnach 適合類型:

impl LimitCollection for ConcreteLimitCollection {
    type Output<'a> = std::iter::Filter<std::slice::Iter<'a, Limit>, fn(&&Limit) -> bool>;
    
    fn get_violated_limits<'a>(&'a self) -> Self::Output<'a> {
        self.limits.iter().filter(|l| l.is_violated())
    }
}

操場

有沒有辦法讓這個構造工作,最好不訴諸動態分配?

泛型類型意味着調用者決定類型是什么,因為I (類型)是一個輸入參數,所以調用者應該能夠傳入他們想要的任何東西,只要它滿足約束。

但這里不是這樣,你讓調用者別無選擇。

讓調用者別無選擇,但給trait 實現者一個選擇的方法是關聯類型。

遺憾的是,正如 Netwave 所指出的,這需要一個通用的關聯類型(因為Iterator在整個生命周期內都是通用'a ),而 GAT 並不穩定。

解決這個問題的兩種方法是參數化 trait 本身,以及為引用而不是類型實現 trait。 https://stackoverflow.com/a/33756123/8182118有示例和可能性討論。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM