首页 > 解决方案 > 如何声明一个可以将稀疏向量的引用添加到一起的通用函数?

问题描述

我正在尝试使用crate sprs版本0.6.3)来操作稀疏向量。我想将两个向量加在一起。我从Addtrait 的实现开始,然后将其简化为实现函数。最后,我将问题归结为一个简单的泛型函数。

// This works: the scalar type `u64` is fixed here
fn adder(first: &CsVec<u64>, second: &CsVec<u64>) -> CsVec<u64> {
    first + second
}

// When I try to make the scalar type generic, it doesn't work
fn adder2<T>(first: &CsVec<T>, second: &CsVec<T>) -> CsVec<T>
where
    CsVec<T>: Add,
    T: Add + Debug,
{
    first + second
}

第一个版本编译得很好,但我想知道为什么第二个版本不能编译。我收到此错误消息:

error[E0369]: binary operation `+` cannot be applied to type `&sprs::sparse::CsVecBase<std::vec::Vec<usize>, std::vec::Vec<T>>`
  --> libp3prime/src/lib/datacache.rs:62:5
   |
62 |     first + second
   |     ^^^^^^^^^^^^^^
   |
   = note: an implementation of `std::ops::Add` might be missing for `&sprs::sparse::CsVecBase<std::vec::Vec<usize>, std::vec::Vec<T>>`

我真的不明白错误信息。我知道你可以将两个加CsVecs在一起,因为adder()编译,所以我有点迷茫。

这两个向量应该加在一起。

标签: rust

解决方案


确保在函数上定义的特征边界与函数中使用的行为相匹配。

first并且second不是CsVec<T>,但是&CsVec<T>。在 Rust 中,&X是与X. 您需要一个 trait bound 来说明您可以添加两个&CsVec<T>s 并获得 aCsVec<T>作为输出:

fn adder2<'a, T>(first: &'a CsVec<T>, second: &'a CsVec<T>) -> CsVec<T>
where
    &'a CsVec<T>: Add<Output = CsVec<T>>,
{
    first + second
}

T在这个例子中不需要限制。

在这种'a情况下,生命周期参数被传递给函数。有时在函数内部的引用上定义一个特征是很有用的,例如,+在对局部变量的引用上使用。在这种情况下,您可能希望使用排名较高的特征绑定 for<'a> &'a CsVec<T>: Add<Output = CsVec<T>>。有关更多信息,请参阅下面的链接问题。

Lukas Kalbertodt 指出,有时说“我只想添加两个&CsVec<T>s,我将返回该操作给我的任何类型”可能会更灵活,您可以通过返回来做到这一点<&'a CsVec<T> as Add>::Output

fn adder2<'a, T>(first: &'a CsVec<T>, second: &'a CsVec<T>) -> <&'a CsVec<T> as Add>::Output
where
    &'a CsVec<T>: Add,
{
    first + second
}

在这种情况下,输出类型不必是完全CsVec<T>的,但是当它是时,它的工作方式与第一个版本相同。

有关的


推荐阅读