移出泛型类型的共享引用

Moving out of a shared reference on a generic type

我正在尝试创建一个函数,该函数使用迭代器为每行中最大的 i64 获取元组“坐标”的 &[Vec<u64>] 和 returns 向量。我让它在具体类型上工作,但我希望它在 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<_>>()
}

我得到:

cannot move out of `*v` which is behind a shared reference

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

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

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

您已经添加了绑定 T: IntoIterator,因为这是唯一的 IntoIterator,编译器将使用 T 的实现。在 T 上调用 into_iter 将始终移动该值,这是不正确的,因为该函数仅被赋予了对它的引用,而 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,

另请参阅: