移出泛型类型的共享引用
我正在尝试创建一个函数,该函数使用迭代器&[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_iter
take self
,这意味着它消耗(或移动)对象。
您已经添加了边界T: IntoIterator
,因为这是唯一的边界,IntoIterator
编译器将使用T
的实现。调用into_iter
上T
会一直移动值,因为该功能只被给它一个参考,这是不正常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 的确切自动解引用规则是什么?