我有一个特征Matrix
和通用函数semi_def<T: Matrix>(x: &T)
,我想对该特征进行操作。该功能要求在Mul
上实现一个运算符特征,例如T
。但是,如果其中一个引用是对局部变量的引用,我似乎无法使一生愉快。当其中之一只是本地临时引用时,如何在类型约束中编写引用的生存期?
use std::ops::Mul;
trait Matrix: Clone {
fn transpose(self) -> Self;
}
#[derive(Clone)]
struct DenseMatrix {
n_rows: usize,
n_columns: usize,
elements: Vec<f64>,
}
impl Matrix for DenseMatrix {
fn transpose(self) -> Self {
unimplemented!()
}
}
impl<'a, 'b> Mul<&'b DenseMatrix> for &'a DenseMatrix {
type Output = DenseMatrix;
fn mul(self, _rhs: &'b DenseMatrix) -> Self::Output {
unimplemented!()
}
}
fn semi_def<'a, T: Matrix>(x: &'a T) -> T
where
&'a T: Mul<&'a T, Output = T>,
{
&(*x).clone().transpose() * x
}
fn main() {}
这给出了这个错误:
error[E0597]: borrowed value does not live long enough
--> src/main.rs:31:6
|
31 | &(*x).clone().transpose() * x
| ^^^^^^^^^^^^^^^^^^^^^^^^ temporary value does not live long enough
32 | }
| - temporary value only lives until here
|
note: borrowed value must be valid for the lifetime 'a as defined on the function body at 27:1...
--> src/main.rs:27:1
|
27 | / fn semi_def<'a, T: Matrix>(x: &'a T) -> T
28 | | where
29 | | &'a T: Mul<&'a T, Output = T>,
30 | | {
31 | | &(*x).clone().transpose() * x
32 | | }
| |_^
最佳答案
您需要较高的特征范围(HRTB),即are described in the advanced Rust book Rustonomicon和on Stack Overflow。它们允许类型约束说特征不仅必须针对具有特定生存期的引用实现,而且还必须针对任何生存期实现。他们使用where for<>
语法。这是函数定义,它表示对Mul
的任何两个引用都需要实现T
:
fn semi_def<'a, T: Matrix>(x: &'a T) -> T
where
for<'b, 'c> &'b T: Mul<&'c T, Output = T>,
{
&(*x).clone().transpose() * x
}
因为其中一个引用实际上具有生存期
'a
,而不是本地生存期,所以可以用稍微宽松一些的约束来编写它:fn semi_def<'a, T: Matrix>(x: &'a T) -> T
where
for<'b> &'b T: Mul<&'a T, Output = T>,
{
&(*x).clone().transpose() * x
}
该问答基于我在Rust用户的邮件中询问的a question的要求,我将其清理并带到这里以供将来的Rustaceans使用。
关于generics - 当其中一个是本地引用时,如何在类型约束中编写引用的生存期?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/61567726/