generics - 当其中一个是本地引用时,如何在类型约束中编写引用的生存期?

标签 generics rust lifetime

我有一个特征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 Rustonomiconon 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/

相关文章:

iterator - 如何使用生命周期嵌套可变访问?

c# - 作为通用值的结构数组

loops - 循环时,.iter() 与引用 (&) 有何不同?

c# - 在编译时检查泛型参数

rust - 如何使用 'on_send'镍 react 的方法?

rust - 如何格式化 const 字符串

Rust 引用在此处被删除,同时仍被借用

C++ 标准 : end of lifetime

swift - 我如何扩展其值就是字典本身的字典?

c# - 参数类型不可分配给参数类型,它应该是