Make IntoIterator trait implementation lifetime-dynamic

huangapple go评论75阅读模式
英文:

Make IntoIterator trait implementation lifetime-dynamic

问题

Here's the translated code without the translation of code comments:

我有这段代码可以运行:

```rust
impl<T> IntoIterator for Range<T>
where
    T: Display + PartialOrd + 'static,
    RangeInclusive<T>: Iterator<Item = T> + DoubleEndedIterator,
    Rev<RangeInclusive<T>>: Iterator<Item = T>,
{
    type Item = T;
    type IntoIter = Box<dyn Iterator<Item = T>>;

    fn into_iter(self) -> Self::IntoIter {
        if self.start > self.end {
            Box::new((self.start..=self.end).rev())
        } else {
            Box::new(self.start..=self.end)
        }
    }
}

我想重构它以使用动态生命周期而不是 'static。但是,我无法弄清楚如何做到这一点,因为我似乎总是遇到 unconstrained lifetime parameter 错误:

impl<'a, T> IntoIterator for Range<T>
where
    T: Display + PartialOrd + 'a,
    RangeInclusive<T>: Iterator<Item = T> + DoubleEndedIterator,
    Rev<RangeInclusive<T>>: Iterator<Item = T>,
{
    type Item = T;
    type IntoIter = Box<dyn Iterator<Item = T> + 'a>;

    fn into_iter(self) -> Self::IntoIter {
        if self.start > self.end {
            Box::new((self.start..=self.end).rev())
        } else {
            Box::new(self.start..=self.end)
        }
    }
}

在这里是否可能使用动态生命周期?

其他类型

#[derive(Clone, Copy, Debug, PartialEq)]
pub struct Range<T>
where
    T: Display + PartialEq,
{
    start: T,
    end: T,
}

impl<T> Range<T>
where
    T: Display + PartialEq,
{
    pub fn new(start: T, end: T) -> Self {
        Self { start, end }
    }
}

错误

error[E0207]: the lifetime parameter 'a is not constrained by the impl trait, self type, or predicates
  --> src/lib.rs:56:6
   |
56 | impl<'a, T> IntoIterator for Range<T>
   |      ^^ unconstrained lifetime parameter

<details>
<summary>英文:</summary>

I have this code which works:

impl<T> IntoIterator for Range<T>
where
T: Display + PartialOrd + 'static,
RangeInclusive<T>: Iterator<Item = T> + DoubleEndedIterator,
Rev<RangeInclusive<T>>: Iterator<Item = T>,
{
type Item = T;
type IntoIter = Box<dyn Iterator<Item = T>>;

fn into_iter(self) -&gt; Self::IntoIter {
    if self.start &gt; self.end {
        Box::new((self.start..=self.end).rev())
    } else {
        Box::new(self.start..=self.end)
    }
}

}

I&#39;d like to refactor it to use a dynamic lifetime instead of `&#39;static`.
However, I cannot figure out how to do this, since I always seem to run into the *unconstrained lifetime parameter* error:

impl<'a, T> IntoIterator for Range<T>
where
T: Display + PartialOrd + 'a,
RangeInclusive<T>: Iterator<Item = T> + DoubleEndedIterator,
Rev<RangeInclusive<T>>: Iterator<Item = T>,
{
type Item = T;
type IntoIter = Box<dyn Iterator<Item = T> + 'a>;

fn into_iter(self) -&gt; Self::IntoIter {
    if self.start &gt; self.end {
        Box::new((self.start..=self.end).rev())
    } else {
        Box::new(self.start..=self.end)
    }
}

}

Is it possible, do use a dynamic lifetime here?

**Orther types**

#[derive(Clone, Copy, Debug, PartialEq)]
pub struct Range<T>
where
T: Display + PartialEq,
{
start: T,
end: T,
}

impl<T> Range<T>
where
T: Display + PartialEq,
{
pub fn new(start: T, end: T) -> Self {
Self { start, end }
}
}


**Error**

error[E0207]: the lifetime parameter &#39;a is not constrained by the impl trait, self type, or predicates
--> src/lib.rs:56:6
|
56 | impl<'a, T> IntoIterator for Range<T>
| ^^ unconstrained lifetime parameter



</details>


# 答案1
**得分**: 1

你可以使用 [`either`](https://docs.rs/either/latest/either/enum.Either.html) 或 [`itertools`](https://docs.rs/itertools/latest/itertools/enum.Either.html) 中的 `Either` 代替 `Box&lt;dyn Iterator&gt;` 来保存两个迭代器中的一个,而不会引起 `dyn Iterator` 引发的生命周期问题。以下是相应的Rust代码:

```rust
impl&lt;T&gt; IntoIterator for Range&lt;T&gt;
where
    T: Display + PartialOrd + &#39;static,
    RangeInclusive&lt;T&gt;: Iterator&lt;Item = T&gt; + DoubleEndedIterator,
{
    type Item = T;
    type IntoIter = Either&lt;Rev&lt;RangeInclusive&lt;T&gt;&gt;, RangeInclusive&lt;T&gt;&gt;;

    fn into_iter(self) -&gt; Self::IntoIter {
        if self.start &gt; self.end {
            Either::Left((self.start..=self.end).rev())
        } else {
            Either::Right(self.start..=self.end)
        }
    }
}
英文:

You can use Either from either or itertools instead of Box&lt;dyn Iterator&gt; to hold one of two iterators, without the lifetime problems caused by dyn Iterator:

impl&lt;T&gt; IntoIterator for Range&lt;T&gt;
where
    T: Display + PartialOrd + &#39;static,
    RangeInclusive&lt;T&gt;: Iterator&lt;Item = T&gt; + DoubleEndedIterator,
{
    type Item = T;
    type IntoIter = Either&lt;Rev&lt;RangeInclusive&lt;T&gt;&gt;, RangeInclusive&lt;T&gt;&gt;;

    fn into_iter(self) -&gt; Self::IntoIter {
        if self.start &gt; self.end {
            Either::Left((self.start..=self.end).rev())
        } else {
            Either::Right(self.start..=self.end)
        }
    }
}

huangapple
  • 本文由 发表于 2023年6月1日 00:47:13
  • 转载请务必保留本文链接:https://go.coder-hub.com/76375728.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定