作为函数参数的 IntoIterator 不接受适配器结构体。

3
我希望有一个函数,可以接受&IntoIterator<Item=u32>类型的参数,这样我就可以将&Vec<u32>和迭代器适配器结构体(例如MapFilter以及其他所有实现了IntoIterator接口的结构体)传递给它。
因此,我需要编写如下的函数:
pub fn f<'a, T>(it_src: &'a T) -> u32
where &'a T: IntoIterator<Item = u32> {
    let it = it_src.into_iter();
    let result: u32;
    // more more usage
    result
}

这是我尝试使用它的方法(相同的签名,但不同的名称)
pub fn f_with_feature()<'a, T>(it_src: &'a T) -> u32
where &'a T: IntoIterator<Item = u32> {
    let adjusted_values = it_src.into_iter()
        .map(|e| adjust(e));
    f(&adjusted_values)
}

我遇到了一个错误

 error[E0308]: mismatched types
  --> src\main.rs:14:7
   |
14 |     f(&adjusted_values)
   |       ^^^^^^^^^^^^^^^^ expected type parameter, found struct `std::iter::Map`
   |
   = note: expected type `&T`
              found type `&std::iter::Map<<&T as std::iter::IntoIterator>::IntoIter, [closure@src\main.rs:13:14: 13:27]>`

为什么Map不能作为T类型匹配?

此外,我想到了一个想法,使用静态分派传递迭代器的适配器并不是一个好主意,因为用于生成Map的每个其他闭包都会创建一个新的函数专业化。尽管在Rust中,大多数情况下采用静态分派方法是成语的。如何处理这种情况?

1个回答

3

我认为您希望在 T 上有特质绑定(而不是在 &'a T 上)。所以我猜您实际上想要以下内容:

pub fn f<'a, T>(it_src: &'a T) -> u32
where T: IntoIterator<Item = u32> {
    let it = it_src.into_iter();
    let result: u32 = 1;
    // more more usage
    result
}

pub fn f_with_feature<'a, T>(it_src: &'a T) -> u32
where T: IntoIterator<Item = u32> {
    let adjusted_values = it_src.into_iter()
        .map(|e| adjust(e));
    f(&adjusted_values)
}

这就引出了下一个问题: IntoIteratorinto_iter 会消耗 self, 这意味着如果你只是借用 it_src,你无法调用 it_src.into_iter
如果你真的想使用 into_iter,可以试试这个方法:
pub fn f<T>(it_src: T) -> u32
where T: IntoIterator<Item = u32> {
    let it = it_src.into_iter();
    let result: u32 = 1;
    // more more usage
    result
}

pub fn f_with_feature<T>(it_src: T) -> u32
where T: IntoIterator<Item = u32> {
    let adjusted_values = it_src.into_iter()
        .map(|e| adjust(e));
    f(adjusted_values)
}

然而,这需要您将值移动到ff_with_feature中。

根据我的经验,只需使用一个迭代器(并在必要时在调用站点进行转换)即可得到简单、直接的解决方案:

pub fn f<T>(it_src: T) -> u32
where T: Iterator<Item = u32> {
    let it = it_src.into_iter();
    let result: u32 = 1;
    // more more usage
    result
}

pub fn f_with_feature<T>(it_src: T) -> u32
where T: Iterator<Item = u32> {
    let adjusted_values = it_src.into_iter()
        .map(|e| adjust(e));
    f(adjusted_values)
}

1
我已经转向使用迭代器方法,但强制传递一个迭代器而不是 &Vec<_> 有些遗憾,因为 &Vec<_> 实现了 IntoIterator 而且不会消耗向量。 - Alexey Larionov
iter() 也不会消耗或复制向量。 - Pr0methean

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接