本文介绍了当其中一个是本地引用时,如何为类型约束中的引用编写生命周期?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个特征 Matrix 和通用函数 semi_def(x: &T) 我想对那个特征进行操作.该函数需要在 T 上实现运算符特征,例如 Mul.但是,如果引用之一是对局部变量,我似乎无法让生命周期快乐.当其中一个只是本地临时引用时,如何为类型约束中的引用编写生命周期?

I have a trait Matrix and generic function semi_def<T: Matrix>(x: &T) that I would like to operate on that trait. The function requires an operator trait, say Mul, be implemented on T. However, I can't seem to make the lifetimes happy if one of the references is to a local variable. How do I write the lifetimes for references in the type constraint when one of them is just a local temporary reference?

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),它在 Rust 高级书籍 Rustonomicon​​关于堆栈溢出.它们允许类型约束说明 trait 不仅必须为具有特定生命周期的引用实现,而且必须为任何生命周期实现.他们使用 where for<> 语法.下面是一个函数定义,它表示对 T 的任意两个引用都需要一个 Mul 的实现:

You need higher-ranked trait bounds (HRTBs), which are described in the advanced Rust book Rustonomicon and well as on Stack Overflow. They allow a type constraint to say that trait must be implemented not just for references with a particular lifetime but for any lifetime. They use the where for<> syntax. Here is the function definition that says an implementation of Mul is needed for any two references to 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,而不是局部生命周期,所以可以用稍微宽松的约束来编写:

Because one of the references actually has the lifetime 'a, not a local lifetime, this could be written with a slightly looser constraint:

fn semi_def<'a, T: Matrix>(x: &'a T) -> T
where
    for<'b> &'b T: Mul<&'a T, Output = T>,
{
    &(*x).clone().transpose() * x
}

这篇关于当其中一个是本地引用时,如何为类型约束中的引用编写生命周期?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

09-02 11:24