用于存储具有不同通用参数的结构的特征
Trait to store structs with different generic parameters
我需要存储相同结构的相同 Vec
个实例,但具有不同的通用参数。这是结构定义:
struct Struct<'a, T: 'a> {
items: Vec<&'a T>
}
该结构有一个方法将迭代器返回到不依赖于泛型类型参数的类型 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())
^~~~~~~~~~~~~~~~~~~~~
我已经尝试了特征中生命周期参数的不同可能性,但是 none 它们都有效。我怎样才能使这项工作?
编辑
正如@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
但它们似乎是一回事。发生什么事了?
问题 1 — slice::Iter<T>
的 Iterator::Item
为 &T
,因此您的参考水平不匹配。将您的方法更改为
fn iter(&self) -> slice::Iter<i32>
问题 2 — Box<SomeTrait>
等同于 Box<SomeTrait + 'static>
,但您的迭代器不会在 'static
生命周期内存在。你需要明确的带入一个生命周期:
Box<SomeTrait + 'a>
问题 3 — 我不明白如何为特征创建类型别名,这看起来很奇怪。无论如何你可能都不想要它。相反,为整个盒装版本创建一个类型别名:
type IterBox<'a> = Box<Iterator<Item=&'a i32> + 'a>;
问题 4 — 重新排列您的 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 }));
}
总计:
use std::slice;
type IterBox<'a> = Box<Iterator<Item=&'a i32> + 'a>;
trait Trait {
fn iter<'a>(&'a self) -> IterBox;
}
struct Struct<'a, T: 'a> {
items: Vec<&'a T>
}
impl<'a, T: 'a> Struct<'a, T> {
fn iter(&self) -> slice::Iter<i32> {
unimplemented!()
}
}
impl<'a, T: 'a> Trait for Struct<'a, T> {
fn iter(&self) -> IterBox {
Box::new(self.iter())
}
}
fn main() {
let i = 3;
let v = vec![&i];
let mut traits: Vec<Box<Trait>> = Vec::new();
traits.push(Box::new(Struct { items: v }));
}
我需要存储相同结构的相同 Vec
个实例,但具有不同的通用参数。这是结构定义:
struct Struct<'a, T: 'a> {
items: Vec<&'a T>
}
该结构有一个方法将迭代器返回到不依赖于泛型类型参数的类型 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())
^~~~~~~~~~~~~~~~~~~~~
我已经尝试了特征中生命周期参数的不同可能性,但是 none 它们都有效。我怎样才能使这项工作?
编辑
正如@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
但它们似乎是一回事。发生什么事了?
问题 1 — slice::Iter<T>
的 Iterator::Item
为 &T
,因此您的参考水平不匹配。将您的方法更改为
fn iter(&self) -> slice::Iter<i32>
问题 2 — Box<SomeTrait>
等同于 Box<SomeTrait + 'static>
,但您的迭代器不会在 'static
生命周期内存在。你需要明确的带入一个生命周期:
Box<SomeTrait + 'a>
问题 3 — 我不明白如何为特征创建类型别名,这看起来很奇怪。无论如何你可能都不想要它。相反,为整个盒装版本创建一个类型别名:
type IterBox<'a> = Box<Iterator<Item=&'a i32> + 'a>;
问题 4 — 重新排列您的 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 }));
}
总计:
use std::slice;
type IterBox<'a> = Box<Iterator<Item=&'a i32> + 'a>;
trait Trait {
fn iter<'a>(&'a self) -> IterBox;
}
struct Struct<'a, T: 'a> {
items: Vec<&'a T>
}
impl<'a, T: 'a> Struct<'a, T> {
fn iter(&self) -> slice::Iter<i32> {
unimplemented!()
}
}
impl<'a, T: 'a> Trait for Struct<'a, T> {
fn iter(&self) -> IterBox {
Box::new(self.iter())
}
}
fn main() {
let i = 3;
let v = vec![&i];
let mut traits: Vec<Box<Trait>> = Vec::new();
traits.push(Box::new(Struct { items: v }));
}