首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >铁锈:定义一个特性,返回一个不消耗迭代器。(T内嵌IntoIterator和&T内嵌IntoIterator的关联类型界)

铁锈:定义一个特性,返回一个不消耗迭代器。(T内嵌IntoIterator和&T内嵌IntoIterator的关联类型界)
EN

Stack Overflow用户
提问于 2022-06-22 21:48:57
回答 1查看 27关注 0票数 0

我想要一个返回泛型集合的特性,让我迭代该集合中的引用。

例如:

代码语言:javascript
运行
复制
trait DuckCollection {
    type CollectionType: IntoIterator<Item=Duck>;
    fn get(self) -> Self::CollectionType;
    fn as_ref(&self) -> &Self::CollectionType;
}

使用迭代器可以工作,但是as_ref存在一个问题。

代码语言:javascript
运行
复制
//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

这可以通过向函数添加特征边界来解决。也就是说,下面的工作是有效的:

代码语言:javascript
运行
复制
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子句,如下所示,并出现了由此产生的错误:

代码语言:javascript
运行
复制
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_defaultsgeneric_associated_types来告诉这个特性,即存在一个名为CollectionTypeRef的关联类型,它实现了IntoIterator,并且该类型是一个CollectionType的引用。如下所示,错误如下:

代码语言:javascript
运行
复制
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的迭代器这一特性?

EN

回答 1

Stack Overflow用户

发布于 2022-06-22 21:55:00

典型的,我一发问题就会想出答案。

完整的解决方案见下文。我仍然想知道是否有一种更优雅的方式来做到这一点。

这仍然需要我把type CollectionTypeRef<'a> = &'a Self::CollectionType;放在推动中,我宁愿成为一个associated_type_default,但这似乎不起作用。

代码语言:javascript
运行
复制
//#![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!");
}
票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/72722376

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档