Rust 无法在包含Cow的结构上重载add运算符,因为我无法返回引用本地数据的值
我正在一个通用字段Rust 无法在包含Cow的结构上重载add运算符,因为我无法返回引用本地数据的值,rust,Rust,我正在一个通用字段F上实现矩阵的基本操作。在执行此操作时,我希望为矩阵类型重载add运算符。矩阵类型包含拥有或借用F的Cow。我希望得到的矩阵和借用所添加矩阵的F,而不管它是拥有还是借用F 编译器抱怨我返回了在函数内部创建的引用,但我不明白为什么。在我看来,我引用的是函数的输入参数,而不是本地创建的数据。下面是我的最简单的例子: use std::{ borrow::{Borrow, Cow}, ops::Add, }; pub trait Field { type F
F
上实现矩阵的基本操作。在执行此操作时,我希望为矩阵类型重载add运算符。矩阵类型包含拥有或借用F
的Cow
。我希望得到的矩阵和借用所添加矩阵的F
,而不管它是拥有还是借用F
编译器抱怨我返回了在函数内部创建的引用,但我不明白为什么。在我看来,我引用的是函数的输入参数,而不是本地创建的数据。下面是我的最简单的例子:
use std::{
borrow::{Borrow, Cow},
ops::Add,
};
pub trait Field {
type FElt: Copy + Eq;
fn zero(&self) -> Self::FElt;
fn add(&self, a: Self::FElt, b: Self::FElt) -> Self::FElt;
}
pub struct Mat<'a, F: Clone + Eq + Field> {
field: Cow<'a, F>,
rows: usize,
cols: usize,
data: Vec<F::FElt>,
}
impl<'a, F: Clone + Eq + Field> Mat<'a, F> {
pub fn zero(field: &'a F, rows: usize, cols: usize) -> Self {
if rows == 0 || cols == 0 {
panic!("Empty matrix");
}
Self {
field: Cow::Borrowed(field),
rows,
cols,
data: vec![field.zero(); rows * cols],
}
}
}
impl<'a, F: Clone + Eq + Field> Add for Mat<'a, F> {
type Output = Self;
fn add(self, other: Self) -> Self::Output {
if self.field != other.field {
panic!("Cannot add matrices: fields do not match");
}
if self.rows != other.rows || self.cols != other.cols {
panic!("Cannot add matrices: dimensions do not match");
}
let f: &F = self.field.borrow();
let mut sum = Mat::zero(f, self.rows, self.cols);
for i in 0..self.rows * self.cols {
sum.data[i] = f.add(self.data[i], other.data[i]);
}
sum
}
}
fn main() {}
在我看来,我引用的是函数的输入参数,而不是本地创建的数据
self
可能不是本地创建的,但是它被移动到了add
方法中(该方法采用self
),因此当函数返回时它仍然会被销毁。如果允许输出引用它,那么一旦函数返回,引用就会悬空
如果希望输出借用输入,则必须将输入作为参考,这意味着为和'b Mat
实现Add
。请参阅注意,输出
类型必须为Mat
对于所提出的问题,还有另一个更简单的解决方案。借用不起作用,因为已将
Cow
导入函数。为什么不把它搬出去?一种简单的方法是修改self并返回它,而不是在函数内部创建sum
fn add(mut self, other: Self) -> Self::Output {
/* ... */
for i in 0..self.rows * self.cols {
self.data[i] = self.field.add(self.data[i], other.data[i]);
}
self
}
你不仅可以避免一个潜在的昂贵的
字段克隆
,而且还可以通过这种方式重用数据
的缓冲区。我怀疑你不想要一个奶牛
,而是想要一个Rc
(或者更可能是幻影数据
)。我不知道Rc
。这正是我想要的,谢谢PhantomData
不起作用,因为我需要存储有关字段F
的信息(并且我希望避免在向量data
的每个元素中重复它)。“借用不起作用,因为Cow被移植到函数中。”=>我知道你在这里做了什么…谢谢你的回答。为参考实现Add
,但我想为Mat
和&Mat
的所有四种组合实现Add
,这样我就可以写a+b了。但我想我所有的麻烦都是因为我按照Jmb的建议在应该选择的地方选择了Cow
。你的简单解决方案在我看来很奇怪。据我所知,如果我写a+b
,我会得到和,但矩阵a
也会在这个过程中变异成我不想要的和。@gwafotapaa
被表达式a+b
消耗,所以代码无法观察到这一点。例如,这也是String
实现Add
的方法。@trentcl我没有想到这一点。我现在明白你的意图了。这是一个很好的解决方案。尽管我现在在代码中使用了Rc
,但我可以从中获益,这是对我最初问题的一个很好的回答。