【问题标题】:Moving out of a shared reference on a generic type移出泛型类型的共享引用
【发布时间】:2021-07-29 20:51:19
【问题描述】:

我正在尝试创建一个函数,该函数采用 &[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<_>>()
}

我明白了:

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

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

另外,对于IntoIterator&lt;Item=u64&gt;,我需要指定u64 还是可以提供更通用的内容?

【问题讨论】:

  • 您可以拥有T: IntoIterator&lt;Item=u64&gt;,因为T&amp;[T] 中,所以它总是在IntoIterator 无法将self 移动到接收器的共享引用后面迭代器。

标签: generics rust traits move-semantics


【解决方案1】:

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

您已经添加了绑定T: IntoIterator,因此,由于这是唯一的IntoIterator,编译器将使用T 的实现。在T 上调用into_iter 将始终移动该值,这是不行的,因为该函数仅被赋予了对它的引用,而T 可能不是Copy - 事实上,对于Vec 它肯定不是不。

但是IntoIterator 也实现了大多数对可迭代类型的引用,例如&amp;Vec&lt;T&gt;,其中项目也是一个引用。这些是可以移动的,因为引用是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,这要求它是@ 987654340@。函数签名将是:

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 更困难的事情。我错过了一些知识的源泉还是这只是很多线索和错误?
  • @marcantonio 肯定有很多东西要学。与其他任何事情一样,通过练习它开始变得更容易,但 Rust 的学习曲线很陡峭 - 尤其是在开始时。
猜你喜欢
  • 2012-02-01
  • 1970-01-01
  • 1970-01-01
  • 2010-10-01
  • 1970-01-01
  • 2010-10-15
  • 1970-01-01
  • 2023-04-08
  • 1970-01-01
相关资源
最近更新 更多