![](/img/trans.png)
[英]Rust return trait object from Option.unwrap_or() for T: 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_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
的迭代器?
典型的,只要我发布问题,我就会找到答案。
请参阅下面的完整解决方案。 我仍然想知道是否有更优雅的方式来做到这一点。
这仍然需要我把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.