除了使用“静态生命周期”之外的其他解决方案
Other solution than using 'static lifetime
这里是代码:
#[derive(Debug, Eq, PartialEq)]
struct Id(u128);
pub struct IdIter(Box<dyn Iterator<Item= Id>>);
impl IdIter {
pub fn new<I: Iterator<Item= Id>>(tmpl: I) -> Self {
Self(Box::new(tmpl))
}
}
impl Iterator for IdIter {
type Item = Id;
fn next(&mut self) -> Option<Self::Item> {
self.0.next()
}
}
pub trait Link {
fn iter_id(&self) -> IdIter;
}
pub fn links(it: impl Iterator<Item= impl Link>) -> impl Iterator<Item= Id> {
it.into_iter().flat_map(|l| l.iter_id())
}
#[cfg(test)]
mod test {
struct X(u128);
impl super::Link for X {
fn iter_id(&self) -> super::IdIter {
super::IdIter(Box::new(Some(super::Id(self.0)).into_iter()))
}
}
#[test]
fn test_links() {
let mut v = super::links([X(1234), X(4321)].into_iter());
assert_eq!(v.next(), Some(super::Id(1234u128)));
assert_eq!(v.next(), Some(super::Id(4321u128)));
assert_eq!(v.next(), None);
}
}
编译器建议使用 'static lifetime 来解决这个问题,但它有点过分了。
我想要的是提供一个特征(此处为 Link
),该特征的迭代器通过 links
函数给出一个 Id
实例的迭代器。该特征也用作标记特征,因此我不能使用其他库。
如何修复编译器错误?
你的错误可以简化为:
pub struct IdIter(Box<dyn Iterator<Item=()>>);
impl IdIter {
pub fn new<I: Iterator<Item=()>>(tmpl: I) -> Self {
Self(Box::new(tmpl))
}
}
错误如下:
error[E0310]: the parameter type `I` may not live long enough
--> src/lib.rs:5:14
|
4 | pub fn new<I: Iterator<Item=()>>(tmpl: I) -> Self {
| -- help: consider adding an explicit lifetime bound `I: 'static`...
5 | Self(Box::new(tmpl))
| ^^^^^^^^^^^^^^
|
note: ...so that the type `I` will meet its required lifetime bounds
--> src/lib.rs:5:14
|
5 | Self(Box::new(tmpl))
| ^^^^^^^^^^^^^^
最初并不明显,但错误指出了发生的大体方向:结构中的 Box<dyn Iterator<Item = ()>>
自动为 Box<dyn Iterator<Item = ()> + 'static>
,而 I
不一定是 'static
。
解决办法是引入新的生命周期:
pub struct IdIter<'a>(Box<dyn Iterator<Item = ()> + 'a>);
impl<'a> IdIter<'a> {
pub fn new<I: Iterator<Item = ()> + 'a>(tmpl: I) -> Self {
Self(Box::new(tmpl))
}
}
它在给定 IdIter
和明确的生命周期并调整程序的几个部分后编译。这是 complete playground example.
#[derive(Debug, Eq, PartialEq)]
pub struct Id(u128);
pub struct IdIter<'a>(Box<dyn Iterator<Item = Id> + 'a>);
impl<'a> IdIter<'a> {
pub fn new<I: Iterator<Item = Id> + 'a>(tmpl: I) -> Self {
Self(Box::new(tmpl))
}
}
impl Iterator for IdIter<'_> {
type Item = Id;
fn next(&mut self) -> Option<Self::Item> {
self.0.next()
}
}
pub trait Link {
fn iter_id(&self) -> IdIter;
}
pub fn links<'a>(it: impl Iterator<Item = &'a (impl Link + 'a)> + 'a) -> impl Iterator<Item = Id> + 'a {
it.flat_map(Link::iter_id)
}
#[cfg(test)]
mod test {
struct X(u128);
impl super::Link for X {
fn iter_id(&self) -> super::IdIter {
super::IdIter(Box::new(Some(super::Id(self.0)).into_iter()))
}
}
#[test]
fn test_links() {
let mut v = super::links([X(1234), X(4321)].iter());
assert_eq!(v.next(), Some(super::Id(1234u128)));
assert_eq!(v.next(), Some(super::Id(4321u128)));
assert_eq!(v.next(), None);
}
}
这里是代码:
#[derive(Debug, Eq, PartialEq)]
struct Id(u128);
pub struct IdIter(Box<dyn Iterator<Item= Id>>);
impl IdIter {
pub fn new<I: Iterator<Item= Id>>(tmpl: I) -> Self {
Self(Box::new(tmpl))
}
}
impl Iterator for IdIter {
type Item = Id;
fn next(&mut self) -> Option<Self::Item> {
self.0.next()
}
}
pub trait Link {
fn iter_id(&self) -> IdIter;
}
pub fn links(it: impl Iterator<Item= impl Link>) -> impl Iterator<Item= Id> {
it.into_iter().flat_map(|l| l.iter_id())
}
#[cfg(test)]
mod test {
struct X(u128);
impl super::Link for X {
fn iter_id(&self) -> super::IdIter {
super::IdIter(Box::new(Some(super::Id(self.0)).into_iter()))
}
}
#[test]
fn test_links() {
let mut v = super::links([X(1234), X(4321)].into_iter());
assert_eq!(v.next(), Some(super::Id(1234u128)));
assert_eq!(v.next(), Some(super::Id(4321u128)));
assert_eq!(v.next(), None);
}
}
编译器建议使用 'static lifetime 来解决这个问题,但它有点过分了。
我想要的是提供一个特征(此处为 Link
),该特征的迭代器通过 links
函数给出一个 Id
实例的迭代器。该特征也用作标记特征,因此我不能使用其他库。
如何修复编译器错误?
你的错误可以简化为:
pub struct IdIter(Box<dyn Iterator<Item=()>>);
impl IdIter {
pub fn new<I: Iterator<Item=()>>(tmpl: I) -> Self {
Self(Box::new(tmpl))
}
}
错误如下:
error[E0310]: the parameter type `I` may not live long enough
--> src/lib.rs:5:14
|
4 | pub fn new<I: Iterator<Item=()>>(tmpl: I) -> Self {
| -- help: consider adding an explicit lifetime bound `I: 'static`...
5 | Self(Box::new(tmpl))
| ^^^^^^^^^^^^^^
|
note: ...so that the type `I` will meet its required lifetime bounds
--> src/lib.rs:5:14
|
5 | Self(Box::new(tmpl))
| ^^^^^^^^^^^^^^
最初并不明显,但错误指出了发生的大体方向:结构中的 Box<dyn Iterator<Item = ()>>
自动为 Box<dyn Iterator<Item = ()> + 'static>
,而 I
不一定是 'static
。
解决办法是引入新的生命周期:
pub struct IdIter<'a>(Box<dyn Iterator<Item = ()> + 'a>);
impl<'a> IdIter<'a> {
pub fn new<I: Iterator<Item = ()> + 'a>(tmpl: I) -> Self {
Self(Box::new(tmpl))
}
}
它在给定 IdIter
和明确的生命周期并调整程序的几个部分后编译。这是 complete playground example.
#[derive(Debug, Eq, PartialEq)]
pub struct Id(u128);
pub struct IdIter<'a>(Box<dyn Iterator<Item = Id> + 'a>);
impl<'a> IdIter<'a> {
pub fn new<I: Iterator<Item = Id> + 'a>(tmpl: I) -> Self {
Self(Box::new(tmpl))
}
}
impl Iterator for IdIter<'_> {
type Item = Id;
fn next(&mut self) -> Option<Self::Item> {
self.0.next()
}
}
pub trait Link {
fn iter_id(&self) -> IdIter;
}
pub fn links<'a>(it: impl Iterator<Item = &'a (impl Link + 'a)> + 'a) -> impl Iterator<Item = Id> + 'a {
it.flat_map(Link::iter_id)
}
#[cfg(test)]
mod test {
struct X(u128);
impl super::Link for X {
fn iter_id(&self) -> super::IdIter {
super::IdIter(Box::new(Some(super::Id(self.0)).into_iter()))
}
}
#[test]
fn test_links() {
let mut v = super::links([X(1234), X(4321)].iter());
assert_eq!(v.next(), Some(super::Id(1234u128)));
assert_eq!(v.next(), Some(super::Id(4321u128)));
assert_eq!(v.next(), None);
}
}