如何以通用方式定义向量(或迭代器)的和?

Mat*_*teo 5 generics sum rust

我有以下sum功能的矢量i32编译和工作正常:

fn sum_vec(s: &Vec<i64>, init: &i64) -> i64 {
    (*s).iter().fold(*init, |acc, &item| acc + item)
}
Run Code Online (Sandbox Code Playgroud)

为了教自己关于Rust泛型,我想为任何T实现表单添加的 类型定义相应的泛型函数add(T, T) -> T.我试过了

use std::ops::Add;

fn sum_gen_1<T: Add>(s: &Vec<T>, init: &T) -> T {
    (*s).iter().fold(*init, |acc, &item| acc + item)
}
Run Code Online (Sandbox Code Playgroud)

但是我收到以下错误

error[E0308]: mismatched types
 --> src/lib.rs:4:42
  |
4 |     (*s).iter().fold(*init, |acc, &item| acc + item)
  |                                          ^^^^^^^^^^ expected type parameter, found associated type
  |
  = note: expected type `T`
             found type `<T as std::ops::Add>::Output`
Run Code Online (Sandbox Code Playgroud)

似乎必须进一步限制特征的实现, Add以便类型Add::Output等于T.在interwebz上找到一些文档(可能是旧版本的Rust)之后,我尝试更改类型约束,即将T: Add<T, T>泛型函数声明为:

fn sum_gen_1<T: Add<T, T>>(s: &Vec<T>, init: &T) -> T
Run Code Online (Sandbox Code Playgroud)

具有与以前相同的功能体.这次我收到了错误

error[E0107]: wrong number of type arguments: expected at most 1, found 2
 --> src/lib.rs:3:17
  |
3 | fn sum_gen_1<T: Add<T, T>>(s: &Vec<T>, init: &T) -> T {
  |                 ^^^^^^^^^ expected at most 1 type argument
Run Code Online (Sandbox Code Playgroud)

完成此任务的正确方法是什么?我应该使用不同的特性而不是Add吗?也许定义我自己的特性并为我希望我sum工作的类型实现它?

我注意到这是一个特性std::iter::AdditiveIterator 似乎使我的实现不必要.但是,它被标记为不稳定,任何使用它的尝试都会在使用rustc-1.0.0-beta时导致编译错误.

小智 7

你几乎得到了它.关联类型必须通过名称/关键字给出,因此您正在寻找Add<T, Output = T>.

随着这种变化,你面临的问题是你自由地复制数字,但没有Copy约束.我建议以下实现:

fn sum_vec<T>(s: &[T], init: &T) -> T
where
    T: Copy + Add<T, Output = T>,
{
    s.iter().fold(*init, |acc, &item| acc + item)
}
Run Code Online (Sandbox Code Playgroud)

改变&Vec<T>&[T]没有效果,但它使功能更通用,并且没有任何损失.

也可以看看: