![](/img/trans.png)
[英]Passing boxed trait object to function accepting generic parameter implementing the trait
[英]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.