移出泛型类型的共享引用

我正在尝试创建一个函数,该函数使用迭代器&[Vec<u64>]i64每行中最大的一个返回元组“坐标”向量。我有它在具体类型上工作,但我希望它是通用的,T并且限制为可迭代类型。到目前为止我的代码:

fn find_largest_per_row<T>(input: &[T]) -> Vec<(usize, usize)> 
where
    T: IntoIterator<Item = u64>,
{
    input
        .iter()
        .enumerate()
        .map(|(r, v)| {
            v.into_iter()
                .enumerate()
                .max_by_key(|&(_, v)| v)
                .map(|(c, _)| (r, c))
                .unwrap()
        })
        .collect::<Vec<_>>()
}
fn find_largest_per_row<T>(input: &[T]) -> Vec<(usize, usize)> 
where
    T: IntoIterator<Item = u64>,
{
    input
        .iter()
        .enumerate()
        .map(|(r, v)| {
            v.into_iter()
                .enumerate()
                .max_by_key(|&(_, v)| v)
                .map(|(c, _)| (r, c))
                .unwrap()
        })
        .collect::<Vec<_>>()
}

我越来越:

我该如何解决?我意识到T是一个参考,所以我尝试了.cloned(),但这没有用。

另外,对于IntoIterator<Item=u64>,我需要指定u64还是可以提供更通用的东西?

回答

IntoIterator::into_itertake self,这意味着它消耗(或移动)对象。

您已经添加了边界T: IntoIterator,因为这是唯一的边界,IntoIterator编译器将使用T的实现。调用into_iterT会一直移动值,因为该功能只被给它一个参考,这是不正常T可能不是Copy-事实上,对于Vec这绝对不是。

IntoIterator也为大多数对可迭代类型的引用而实现,例如&Vec<T>,其中的项也是引用。这些可以移动,因为引用是Copy,所以原始数据在移动时保持不变。

您可以像这样更改函数签名:

fn find_largest_per_row<'a, T>(input: &'a [T]) -> Vec<(usize, usize)>
where
    &'a T: IntoIterator<Item = &'a u64>,
{
    input
        .iter()
        .enumerate()
        .map(|(r, v)| {
            v.into_iter()
                .enumerate()
                .max_by_key(|&(_, v)| v)
                .map(|(c, _)| (r, c))
                .unwrap()
        })
        .collect::<Vec<_>>()
}

要回答第二个问题,是的,您可以使项目通用。您可以省略它,然后指定代码所需的边界,而不是指定具体类型。您正在按值移动它,因此它需要是Copy(或者您需要更改代码以克隆它并Clone改为使用它),并且您正在使用max_by_key,这要求它是Ord. 函数签名将是:

fn find_largest_per_row<'a, T>(input: &'a [T]) -> Vec<(usize, usize)>
where
    &'a T: IntoIterator,
    <&'a T as IntoIterator>::Item: Ord + Copy,

也可以看看:

  • Rust 的确切自动解引用规则是什么?

以上是移出泛型类型的共享引用的全部内容。
THE END
分享
二维码
< <上一篇
下一篇>>