我想要一个返回泛型集合的特性,让我迭代该集合中的引用。
例如:
trait DuckCollection {
type CollectionType: IntoIterator<Item=Duck>;
fn get(self) -> Self::CollectionType;
fn as_ref(&self) -> &Self::CollectionType;
}使用迭代器可以工作,但是as_ref存在一个问题。
//doesn't work
fn print<T: DuckCollection>(model: &T) {
let collection_ref = model.as_ref();
for itemref in (collection_ref).into_iter() {
println!("{:?}", *itemref);
}
}这不起作用,因为当.into_iter()在collection_ref上被调用时,collection_ref被迫从&<T as DuckCollection>::CollectionType到<T as DuckCollection>::CollectionType,因为DuckCollection不知道&<T as DuckCollection>::CollectionType也实现了IntoIterator

这可以通过向函数添加特征边界来解决。也就是说,下面的工作是有效的:
fn print<'a, T: DuckCollection>(model: &'a T)
where &'a<T as DuckCollection>::CollectionType: IntoIterator<Item=&'a Duck>
{
let collection_ref = model.as_ref();
for itemref in collection_ref.into_iter() {
println!("{:?}", *itemref);
}
}但是,我希望将这些信息放在特征本身中,而不是在使用它的代码中,因此我尝试在属性返回类型中使用where子句,如下所示,并出现了由此产生的错误:
impl DuckCollection for Model {
type CollectionType = Vec<Duck>;
fn get(self) -> Self::CollectionType {
self.data
}
fn as_ref<'a>(&'a self) -> &Self::CollectionType where &'a<Self>::CollectionType: IntoIterator<Item=&'a Duck> {
&self.data
}
}
fn print<T: DuckCollection>(model: &T)
{
let collection_ref = model.as_ref();
for itemref in collection_ref.into_iter() {
println!("{:?}", *itemref);
}
}
`&<T as DuckCollection>::CollectionType` is not an iterator
the trait `Iterator` is not implemented for `&<T as DuckCollection>::CollectionType`
required because of the requirements on the impl of `IntoIterator` for `&<T as DuckCollection>::CollectionType`这种类型不再被强迫,但它仍然没有意识到&<T as DuckCollection>::CollectionType是一个IntoIterator。(即Vec<T>和&Vec<T> impl IntoIterator)。这很烦人,因为我非常肯定,我的where子句告诉编译器这一点。
我还尝试使用associated_type_defaults和generic_associated_types来告诉这个特性,即存在一个名为CollectionTypeRef的关联类型,它实现了IntoIterator,并且该类型是一个CollectionType的引用。如下所示,错误如下:
trait DuckCollection {
type CollectionType: IntoIterator<Item=Duck>;
type CollectionTypeRef<'a>: IntoIterator<Item=&'a Duck> = &'a Self::CollectionType;
fn get(self) -> Self::CollectionType;
fn as_ref<'a>(&self) -> Self::CollectionTypeRef<'a>;
}
the associated type `<Self as DuckCollection>::CollectionType` may not live long enough
...so that the reference type `&'a <Self as DuckCollection>::CollectionType` does not outlive the data it points at我怎么才能解决这个问题?我如何知道get返回可以转换为Duck的迭代器,而as_ref返回&Duck的迭代器这一特性?
发布于 2022-06-22 21:55:00
典型的,我一发问题就会想出答案。
完整的解决方案见下文。我仍然想知道是否有一种更优雅的方式来做到这一点。
这仍然需要我把type CollectionTypeRef<'a> = &'a Self::CollectionType;放在推动中,我宁愿成为一个associated_type_default,但这似乎不起作用。
//#![feature(associated_type_defaults)]
#![feature(generic_associated_types)]
#[derive(Debug)]
struct Duck;
trait DuckCollection {
type CollectionType: IntoIterator<Item=Duck>;
type CollectionTypeRef<'a>: IntoIterator<Item= &'a Duck> where Self: 'a;
fn get(self) -> Self::CollectionType;
fn as_ref<'a>(&'a self) -> Self::CollectionTypeRef<'a>;
}
struct Model {data: Vec<Duck>}
impl DuckCollection for Model {
type CollectionType = Vec<Duck>;
type CollectionTypeRef<'a> = &'a Self::CollectionType;
fn get(self) -> Self::CollectionType {
self.data
}
fn as_ref<'a>(&'a self) -> Self::CollectionTypeRef<'a> {
&self.data
}
}
fn print<T: DuckCollection>(model: &T)
{
let collection_ref = model.as_ref();
for itemref in collection_ref.into_iter() {
println!("{:?}", *itemref);
}
}
fn main() {
let model = Model {
data: vec![Duck, Duck],
};
print(&model);
println!("Hello, world!");
}https://stackoverflow.com/questions/72722376
复制相似问题