首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >创建为IntoIterator复制的方法

创建为IntoIterator复制的方法
EN

Stack Overflow用户
提问于 2021-02-18 11:43:05
回答 2查看 163关注 0票数 1

首先,我想要一个函数,它可以使用泛型集合,但不会使用它。也就是说,我们有一个函数non_consuming

代码语言:javascript
复制
fn non_consuming<'a,I>(_: &'a I)
where &'a I: std::iter::IntoIterator<Item = usize> {}

由于特定的原因,我无法将Item要求更改为&usize。这样的编译器会抛出一个错误,如果我想通常使用这个方法,如下所示:

代码语言:javascript
复制
non_consuming(&vec![0usize,1,2]);

因为IntoIterator是为&Vec实现的,而是用Item = &T实现的。这样,我就有了实现像已复制这样的东西的想法,但是实现的是IntoIterator而不是Iterator

我的目标是为任何带有into_copiedIntoIterator创建一个方法Item: &T,它返回一个用Item: T 实现IntoIterator的结构C &C也应该用Item: T实现IntoIterator

我使用扩展特性为任何into_copied实现IntoIterator,代码的其余部分都非常关注copied是如何实现的:

代码语言:javascript
复制
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

代码语言:javascript
复制
let into_iter_adap = (&vec![0usize,1,2]).into_copied();
non_consuming(&into_iter_adap);

然而,这是我得到的错误:

代码语言:javascript
复制
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实现,那么为什么注释告诉我它将被实现呢?

铁锈游乐场

EN

回答 2

Stack Overflow用户

发布于 2021-02-18 13:04:20

这里有大量的噪音分散了我想象的目标。我们一次只吃一件吧。

放松non_consuming的签名

non_consuming有一个不必要的限制函数签名:它要求它的参数以&I形式表示,而它实际上只需要参数为IntoIterator<Item = usize>。这意味着,即使您有一个Vec<usize>要传递(您不需要,但请容忍我),您也不能将它传递给non_consuming;您将不得不将它保存在调用方中。在没有必要的情况下,决定是否消费应该是调用方的问题;这个函数不应该关心。我们可以在不失去一般性的情况下重写它:

代码语言:javascript
复制
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>的扩展特性。

代码语言:javascript
复制
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()传递给它:

代码语言:javascript
复制
fn main() {
    let vec_ref = &vec![0usize, 1, 2];
    maybe_consuming(vec_ref.into_copied());
}
票数 1
EN

Stack Overflow用户

发布于 2021-02-18 12:29:00

由于@kmdreko的注释,我得到了要编译的代码。我只需要为IntoIterator实现&IntoIterCopied,所以我添加了

代码语言:javascript
复制
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()
    }
}

密码就能正常工作了。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/66259256

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档