首先,我想要一个函数,它可以使用泛型集合,但不会使用它。也就是说,我们有一个函数non_consuming。
fn non_consuming<'a,I>(_: &'a I)
where &'a I: std::iter::IntoIterator<Item = usize> {}由于特定的原因,我无法将Item要求更改为&usize。这样的编译器会抛出一个错误,如果我想通常使用这个方法,如下所示:
non_consuming(&vec![0usize,1,2]);因为IntoIterator是为&Vec实现的,而是用Item = &T实现的。这样,我就有了实现像已复制这样的东西的想法,但是实现的是IntoIterator而不是Iterator。
我的目标是为任何带有into_copied的IntoIterator创建一个方法Item: &T,它返回一个用Item: T 实现IntoIterator的结构C, &C也应该用Item: T实现IntoIterator。
我使用扩展特性为任何into_copied实现IntoIterator,代码的其余部分都非常关注copied是如何实现的:
pub struct IntoIterCopied<I>
{
into_iter: I,
}
impl<I> IntoIterCopied<I>
{
pub fn new(iter: I) -> Self {
IntoIterCopied{
into_iter: iter,
}
}
}
impl<'a,I,T> IntoIterator for IntoIterCopied<I>
where
I: IntoIterator<Item = &'a T>,
T: 'a + Copy
{
type Item = T;
type IntoIter = std::iter::Copied<I::IntoIter>;
fn into_iter(self) -> Self::IntoIter {
self.into_iter.into_iter().copied()
}
}
pub trait IntoIterCopiedExt {
fn into_copied<'a, T>(self) -> IntoIterCopied<Self>
where
Self: Sized + IntoIterator<Item = &'a T>,
T: 'a + Copy
{
IntoIterCopied::new(self)
}
}
impl<T> IntoIterCopiedExt for T
where T: IntoIterator {}我想我现在可以像这样使用函数non_consuming:
let into_iter_adap = (&vec![0usize,1,2]).into_copied();
non_consuming(&into_iter_adap);然而,这是我得到的错误:
error[E0277]: `&IntoIterCopied<&Vec<usize>>` is not an iterator
--> src/main.rs:46:19
|
40 | fn non_consuming<'a,I>(_: &'a I)
| ------------- required by a bound in this
41 | where &'a I: std::iter::IntoIterator<Item = usize>
| ------------------------------------- required by this bound in `non_consuming`
...
46 | non_consuming(&into_iter_adap);
| ^^^^^^^^^^^^^^^ `&IntoIterCopied<&Vec<usize>>` is not an iterator
|
= help: the trait `Iterator` is not implemented for `&IntoIterCopied<&Vec<usize>>`
= note: required because of the requirements on the impl of `IntoIterator` for `&IntoIterCopied<&Vec<usize>>`我不太清楚这个错误告诉了我什么。我为IntoIterCopied实现了IntoIterCopied,但没有为&IntoIterCopied实现,那么为什么注释告诉我它将被实现呢?
发布于 2021-02-18 13:04:20
这里有大量的噪音分散了我想象的目标。我们一次只吃一件吧。
放松non_consuming的签名
non_consuming有一个不必要的限制函数签名:它要求它的参数以&I形式表示,而它实际上只需要参数为IntoIterator<Item = usize>。这意味着,即使您有一个Vec<usize>要传递(您不需要,但请容忍我),您也不能将它传递给non_consuming;您将不得不将它保存在调用方中。在没有必要的情况下,决定是否消费应该是调用方的问题;这个函数不应该关心。我们可以在不失去一般性的情况下重写它:
fn maybe_consuming<II>(_: II)
where
II: std::iter::IntoIterator<Item = usize>,
{
}maybe_consuming仍然会接受non_consuming会提供的任何引用,因为II可以是引用。
替换IntoIterCopied
您不需要将一个IntoIterator包装在一个结构中,就可以给它一个into_copied方法。(如果希望&a_vec总是产生usize,可以考虑包装a_vec,但在这种情况下似乎没有必要。)您只需创建一个提供into_copied并直接返回Copied<Self::IntoIter>的扩展特性。
pub trait IntoCopied {
fn into_copied<'a, T>(self) -> std::iter::Copied<Self::IntoIter>
where
Self: Sized + IntoIterator<Item = &'a T>,
T: 'a + Copy,
{
self.into_iter().copied()
}
}
impl<I> IntoCopied for I where I: IntoIterator {}因为Copied<I>是一个Iterator,因此实现了IntoIterator,所以任何与原始版本一起工作的代码都应该使用这个版本。
修复呼叫者
由于maybe_consuming已经更改为允许非引用,所以我们可以直接将.into_copied()传递给它:
fn main() {
let vec_ref = &vec![0usize, 1, 2];
maybe_consuming(vec_ref.into_copied());
}发布于 2021-02-18 12:29:00
由于@kmdreko的注释,我得到了要编译的代码。我只需要为IntoIterator实现&IntoIterCopied,所以我添加了
impl<'a,I,T> IntoIterator for &'a IntoIterCopied<I>
where
I: IntoIterator<Item = &'a T> + Copy,
T: 'a + Copy
{
type Item = T;
type IntoIter = std::iter::Copied<I::IntoIter>;
fn into_iter(self) -> Self::IntoIter {
self.into_iter.into_iter().copied()
}
}密码就能正常工作了。
https://stackoverflow.com/questions/66259256
复制相似问题