我需要存储在相同结构的相同Vec
个实例中,但具有不同的通用参数。这是结构定义:
struct Struct<'a, T: 'a> {
items: Vec<&'a T>
}
struct有一个方法,它将迭代器返回给不依赖于泛型类型参数T
的类型:
impl<'a, T: 'a> Struct<'a, T> {
fn iter(&self) -> slice::Iter<&i32> {
unimplemented!()
}
}
我需要为向量中的那些不同结构访问此方法,所以我实现了这个特性:
type Iter<'a> = Iterator<Item=&'a i32>;
trait Trait {
fn iter(&self) -> Box<Iter>;
}
我已经实现了Struct
的特性:
impl<'a, T: 'a> Trait for Struct<'a, T> {
fn iter(&self) -> Box<Iter> {
Box::new(self.iter())
}
}
但是编译器抱怨道:
<anon>:21:9: 21:30 error: type mismatch resolving `<core::slice::Iter<'_, &i32> as core::iter::Iterator>::Item == &i32`:
expected &-ptr,
found i32 [E0271]
<anon>:21 Box::new(self.iter())
^~~~~~~~~~~~~~~~~~~~~
<anon>:21:9: 21:30 help: see the detailed explanation for E0271
<anon>:21:9: 21:30 note: required for the cast to the object type `core::iter::Iterator<Item=&i32> + 'static`
<anon>:21 Box::new(self.iter())
^~~~~~~~~~~~~~~~~~~~~
我已尝试过特征中生命参数的不同可能性,但它们都不起作用。我怎样才能做到这一点?
修改
正如@MatthieuM指出的那样。一个问题是类型别名不能正常工作。以下是证明这一点的另一个例子:
use std::slice;
type Iter<'a> = Iterator<Item=&'a i32>;
struct Struct<'a> { _phantom: std::marker::PhantomData<&'a i32> }
impl<'a> Struct<'a> {
fn direct<'b>(i: &'b slice::Iter<'a, i32>) -> &'b Iterator<Item=&'a i32>
{ i }
fn aliased<'b>(i: &'b slice::Iter<'a, i32>) -> &'b Iter<'a>
{ i }
}
在此示例中,direct
编译,但aliased
没有编译,错误:
<anon>:12:7: 12:8 error: the type `core::slice::Iter<'a, i32>` does not fulfill the required lifetime
<anon>:12 { i }
^
note: type must outlive the static lifetime
但他们似乎是一回事。发生了什么?
答案 0 :(得分:2)
问题1 - slice::Iter<T>
的{{1}} Iterator::Item
,因此您的参考级别不匹配。将您的方法更改为
&T
问题2 - fn iter(&self) -> slice::Iter<i32>
等同于Box<SomeTrait>
,但您的迭代器不会在Box<SomeTrait + 'static>
生命周期内存活。你需要明确地带来一生:
'static
问题3 - 我不明白如何为特征创建类型别名,这看起来很奇怪。无论如何,你可能不想要它。而是为整个盒装版本创建一个类型别名:
Box<SomeTrait + 'a>
问题4 - 重新排列type IterBox<'a> = Box<Iterator<Item=&'a i32> + 'a>;
,以便引用能够存活足够长并增加可变性:
main
所有在一起:
fn main() {
let i = 3;
let v = vec![&i];
let mut traits : Vec<Box<Trait>> = Vec::new();
traits.push(Box::new(Struct{ items: v }));
}