首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >强制迭代器返回值而不是引用的正确方法是什么(反之亦然)?

强制迭代器返回值而不是引用的正确方法是什么(反之亦然)?
EN

Stack Overflow用户
提问于 2019-10-13 05:40:02
回答 1查看 413关注 0票数 2

一般的设置是,我有一个想要map()的值数组,然后是一个附加值的chain()。我从这个答案中了解到,构建最终值的正确方法是使用std::iter::once这样做,并消除了以下问题,但我仍然希望更好地理解它的

在我破碎的、可能是防锈的例子中,我使用了一个单一元素数组,然后调用了into_iter()。这在链中产生了值/引用类型不匹配。

问题:,纠正这个值/引用错配的锈蚀惯用机制是什么?特别是如果clonecopy不可用的话。

背景:为什么一开始就有一种类型的错误匹配?

我相信我能理解。基于std::iter::Map的定义,迭代器的项类型为type Item = B,其中BF: FnMut(<I as Iterator>::Item) -> B (即映射类型)的约束。然而,数组定义了以下两个IntoIterator实现,这两个实现似乎都产生引用。

代码语言:javascript
复制
impl<'a, const N: usize, T> IntoIterator for &'a [T; N] where
    [T; N]: LengthAtMost32, 
type Item = &'a T

impl<'a, const N: usize, T> IntoIterator for &'a mut [T; N] where
    [T; N]: LengthAtMost32, 
type Item = &'a mut T

演示这一问题的实例:

代码语言:javascript
复制
#[derive(PartialEq, Eq, Clone, Copy)]
enum Enum1 {
    A, B, C
}

#[derive(PartialEq, Eq, Clone, Copy)]
enum Enum2 {
    X, Y, Z
}

struct Data {
    // Other data omitted
    e1: Enum1,
    e2: Enum2
}
struct Consumer {
    // Other data omitted

    /** Predicate which evaluates if this consumer can consume given Data */
    consumes: Box<dyn Fn(&Data) -> bool>
}


fn main() {
    // Objective: 3 consumers which consume data with A, B, and X respectively
    let v: Vec<Consumer> = [Enum1::A, Enum1::B].iter()
        .map(|&e1| Consumer { consumes: Box::new(move |data| data.e1 == e1) })
        // This chain results in an iterator type-mismatch: 
        // expected &Consumer, found Consumer
        .chain([Consumer { consumes: Box::new(move |data| data.e2 == Enum2::X) }].into_iter())
        .collect(); // Fails as well due to the chain failure

}

错误:

代码语言:javascript
复制
error[E0271]: type mismatch resolving `<std::slice::Iter<'_, Consumer> as std::iter::IntoIterator>::Item == Consumer`
  --> src/main.rs:52:10
   |
52 |         .chain([Consumer { consumes: Box::new(move |data| data.e2 == Enum2::X) }].into_iter())
   |          ^^^^^ expected reference, found struct `Consumer`
   |
   = note: expected type `&Consumer`
              found type `Consumer`

生锈操场实例

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2019-10-13 09:38:31

关于这一点有一个长期存在的问题。技术细节有点重,但从本质上讲,由于底层的技术原因,如果没有大量的hocus,就不能拥有固定大小的数组并返回拥有的引用。当您考虑到什么是固定大小的数组,它是如何存储在内存中,以及如何在不克隆元素的情况下获取元素时,这一点就变得显而易见了。

因此,由于您已经找到了实现,所以只能获得借用的引用。可以使用arrayvec绕过这一问题(因为它们有一个具有自己类型的IntoIterator for ArrayVec的良好实现),或者您可以要求您的所有T: Clone并以这样的方式处理它,而代价是内存中的额外项(临时的;编译器90%的优化时间)。

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

https://stackoverflow.com/questions/58360894

复制
相关文章

相似问题

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