我正在尝试使用num crate Float
trait在我的库中实现泛型,但我一直坚持与编译器作战。这有效:
struct Vector<T> {
data: Vec<T>,
}
trait Metric<T> {
fn norm(&self) -> T;
}
impl Metric<f32> for Vector<f32> {
fn norm(&self) -> f32 {
let mut s = 0.0;
for u in &self.data {
s = s + u * u;
}
s.sqrt()
}
}
但这不是:
use num::Float; // 0.2.0
struct Vector<T> {
data: Vec<T>,
}
trait Metric<T> {
fn norm(&self) -> T;
}
impl<T: Float> Metric<T> for Vector<T> {
fn norm(&self) -> T {
let mut s = T::zero();
for u in &self.data {
s = s + u * u;
}
s.sqrt()
}
}
后者给我以下错误:
error[E0369]: binary operation `*` cannot be applied to type `&T`
--> src/lib.rs:16:23
|
16 | s = s + u * u;
| - ^ - &T
| |
| &T
|
= note: an implementation of `std::ops::Mul` might be missing for `&T`
如果我删除引用并进行迭代,则会self.data
得到一个
error[E0507]: cannot move out of borrowed content
--> src/lib.rs:15:18
|
15 | for u in self.data {
| ^^^^^^^^^ cannot move out of borrowed content
让我们仔细看看这个Float
特征。它定义为:
pub trait Float: NumCast + Num + Copy + Neg<Output = Self> + PartialOrd<Self> {
// ...
}
深入研究Num
特质,我们看到:
pub trait Num: Zero + One + NumOps<Self, Self> + PartialEq<Self> {
// ...
}
更深入 NumOps
pub trait NumOps<Rhs = Self, Output = Self>:
Add<Rhs, Output = Output>
+ Sub<Rhs, Output = Output>
+ Mul<Rhs, Output = Output>
+ Div<Rhs, Output = Output>
+ Rem<Rhs, Output = Output>
{
// ...
}
这意味着任何实现的类型Float
都可以乘以自己的类型。现在,让我们回到您的代码。您正在遍历a Vec<T>
,这为您提供了对每个项目a的引用&T
。
您有一个&T
,正尝试将其乘以另一个&T
。这是一个简化的示例:
fn do_a_thing<T>(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;
}
或者,您可以添加另一个范围,该范围要求可以乘以对您的类型的引用:
impl<T> Metric<T> for Vector<T>
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
正文中添加界限并编写更简单的代码:
impl<T> Metric<T> for Vector<T>
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()
}
}
也可以看看:
本文收集自互联网,转载请注明来源。
如有侵权,请联系[email protected] 删除。
我来说两句