让我们仔细看看这个Float
特征。它定义为:
pub trait Float: NumCast + Num + Copy + Neg
深入研究此Num
特征,我们看到:
pub trait Num: Zero + One + NumOps+ PartialEq { // ... }
更深入 NumOps
pub trait NumOps: Add + Sub + Mul + Div + Rem { // ... }
这意味着实现的任何类型Float
都可以乘以自己的类型。现在,让我们回到您的代码。您正在遍历a Vec
,这为您提供了对每个项目a的引用&T
。
您有一个&T
,正尝试将其乘以另一个&T
。这是一个简化的示例:
fn do_a_thing(a: &T, b: &T) where T: Float, { let z = a * b; }
这给出了相同的错误:binary operation `*` cannot be applied to type `&T`
。
问题是您只知道可以将a乘以T
另一个T
。也就是说,您必须显式取消引用变量。既然Float
也需要Copy
,这将起作用:
let z = (*a) * (*b);
将相同的更改应用于原始代码将使其正常工作:
for u in &self.data { s = s + (*u) * (*u); }
您还可以在模式匹配时取消引用迭代器变量:
for &u in &self.data { s = s + u * u; }
或者,您可以添加另一个范围,该范围要求可以乘以对您的类型的引用:
implMetric for Vector where T: Float, for<'a> &'a T: std::ops::Mul<&'a T, Output = T>, { fn norm(&self) -> T { let mut s = T::zero(); for u in &self.data { s = s + u * u; } s.sqrt() } }
您还可以在AddAssign
正文中添加界限并编写更简单的代码:
implMetric for Vector where T: Float + std::ops::AddAssign, for<'a> &'a T: std::ops::Mul<&'a T, Output = T>, { fn norm(&self) -> T { let mut s = T::zero(); for u in &self.data { s += u * u; } s.sqrt() } }
也可以看看:
如何编写一个特征绑定以添加两个泛型类型的引用?
当其中一个是本地引用时,如何在类型约束中编写引用的生存期?
for <>语法与常规生存期限制有何不同?