尽管在here和here之前已经对此进行了讨论,但是我无法完全实现一个简单的示例。在代码中
// Create some random type that we want to represent as a Real
struct Foo<Real> {
x: Real,
y: Real,
}
// Add the algebra for Foo
impl<Real> std::ops::Add for Foo<Real>
where
Real: std::ops::Add<Output = Real> + std::ops::Mul<Output = Real>,
{
type Output = Self;
fn add(self, other: Self) -> Self::Output {
Foo {
x: self.x + other.x,
y: self.y + other.y,
}
}
}
impl<Real> std::ops::Mul for Foo<Real>
where
Real: std::ops::Add<Output = Real> + std::ops::Mul<Output = Real>,
{
type Output = Self;
fn mul(self, other: Self) -> Self::Output {
Foo {
x: self.x * other.x,
y: self.y * other.y,
}
}
}
// Compute a function on a slice of Reals
fn foo<Real>(x: &[Real]) -> Real
where
for<'a> &'a Real: std::ops::Add<Output = Real> + std::ops::Mul<Output = Real>,
{
&(&x[0] + &x[1]) * &x[2]
}
// Run foo on two different types
fn main() {
let x = vec![1.2, 2.3, 3.4];
let _x = foo::<f64>(&x);
let y: Vec<Foo<f64>> = x.into_iter().map(|z| Foo { x: z, y: z + 1.0 }).collect();
let _y = foo::<Foo<f64>>(&y);
}
我们收到编译器错误:
error[E0277]: cannot add `&'a Foo<f64>` to `&'a Foo<f64>`
--> src/main.rs:47:14
|
47 | let _y = foo::<Foo<f64>>(&y);
| ^^^^^^^^^^^^^^^ no implementation for `&'a Foo<f64> + &'a Foo<f64>`
|
= help: the trait `std::ops::Add` is not implemented for `&'a Foo<f64>`
note: required by `foo`
--> src/main.rs:35:1
|
35 | / fn foo<Real>(x: &[Real]) -> Real
36 | | where
37 | | for<'a> &'a Real: std::ops::Add<Output = Real> + std::ops::Mul<Output = Real>,
38 | | {
39 | | &(&x[0] + &x[1]) * &x[2]
40 | | }
| |_^
error[E0277]: cannot multiply `&'a Foo<f64>` to `&'a Foo<f64>`
--> src/main.rs:47:14
|
47 | let _y = foo::<Foo<f64>>(&y);
| ^^^^^^^^^^^^^^^ no implementation for `&'a Foo<f64> * &'a Foo<f64>`
|
= help: the trait `std::ops::Mul` is not implemented for `&'a Foo<f64>`
note: required by `foo`
--> src/main.rs:35:1
|
35 | / fn foo<Real>(x: &[Real]) -> Real
36 | | where
37 | | for<'a> &'a Real: std::ops::Add<Output = Real> + std::ops::Mul<Output = Real>,
38 | | {
39 | | &(&x[0] + &x[1]) * &x[2]
40 | | }
| |_^
这似乎暗示Add
和Mul
的定义不正确。有固定定义的简便方法吗?如果有所作为,我希望让Add
和Mul
不拥有他们的观点。相反,我想让每个运算符分配新的内存,然后将该变量的所有权提供给调用函数。
如前所述,这是以下两个问题的重复
How do I implement the Add trait for a reference to a struct?
How to write a trait bound for adding two references of a generic type?
为了后代,这是@Shepmaster的工作代码:
use std::ops::{Add, Mul};
// Create some random type that we want to represent as a Real
struct Foo<Real> {
x: Real,
y: Real,
}
// Add the algebra for Foo
impl<Real> Add for &'_ Foo<Real>
where
for<'a> &'a Real: Add<Output = Real> + Mul<Output = Real>,
{
type Output = Foo<Real>;
fn add(self, other: Self) -> Self::Output {
Foo {
x: &self.x + &other.x,
y: &self.y + &other.y,
}
}
}
impl<Real> Mul for &'_ Foo<Real>
where
for<'a> &'a Real: Add<Output = Real> + Mul<Output = Real>,
{
type Output = Foo<Real>;
fn mul(self, other: Self) -> Self::Output {
Foo {
x: &self.x * &other.x,
y: &self.y * &other.y,
}
}
}
// Compute a function on a slice of Reals
fn foo<Real>(x: &[Real]) -> Real
where
for<'a> &'a Real: std::ops::Add<Output = Real> + std::ops::Mul<Output = Real>,
{
&(&x[0] + &x[1]) * &x[2]
}
// Run foo on two different types
fn main() {
let x = vec![1.2, 2.3, 3.4];
let _x = foo::<f64>(&x);
let y: Vec<Foo<f64>> = x.into_iter().map(|z| Foo { x: z, y: z + 1.0 }).collect();
let _y = foo::<Foo<f64>>(&y);
}