繁体   English   中英

rust:定义一个返回非消耗迭代器的特征。 (T impls IntoIterator 和 &T impls IntoIterator 的关联类型界限)

[英]rust: Define a trait that returns a non consuming iterator. (associated type bounds for both T impls IntoIterator and &T impls IntoIterator)

我想要一个返回通用集合并让我迭代该集合中的引用的特征。

例如:

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);
    }  
}

这不起作用,因为当在collection_ref上调用.into_iter()时, 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);
    }  
}

但是,我希望在 trait 本身中包含这些信息,而不是在使用它的代码中,所以我尝试在 trait 返回类型中使用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_defaultsgeneric_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的迭代器?

典型的,只要我发布问题,我就会找到答案。

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

这仍然需要我把type CollectionTypeRef<'a> = &'a Self::CollectionType; 在 impl 中,我宁愿那是一个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!");
}

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM