这个问题在这里已有答案:
我正在尝试使用the sprs
crate(版本0.6.3
)来操纵稀疏向量。我想在一起添加两个向量。我开始使用Add
特性的实现,然后将其简化为实现函数。最后,我把这个问题简化为一个简单的泛型函数。
// 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()
编译,所以我有点迷失。
两个向量应该加在一起。
确保函数上定义的特征边界与函数中使用的行为匹配。
first
和second
不是CsVec<T>
,而是&CsVec<T>
。在Rust,&X
是与X
不同的类型。您需要一个特征限制,表示您可以添加两个&CsVec<T>
s并获得CsVec<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>
,但是当它出现时,它的工作方式与第一个版本相同。