当其中一个是本地引用时,如何为类型约束中的引用编写生命周期?

Posted

技术标签:

【中文标题】当其中一个是本地引用时,如何为类型约束中的引用编写生命周期?【英文标题】:How do I write the lifetimes for references in a type constraint when one of them is a local reference? 【发布时间】:2017-11-04 16:55:54 【问题描述】:

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

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 | | 
   | |_^

【问题讨论】:

【参考方案1】:

您需要更高级别的特征边界 (HRTB),即 are described in the advanced Rust book Rustonomicon 和 on Stack Overflow。它们允许类型约束说明 trait 不仅必须针对具有特定生命周期的引用实现,而且必须针对任何生命周期实现。他们使用where for&lt;&gt; 语法。下面是函数定义,表明对T 的任何两个引用都需要实现Mul

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

这个问答是基于a question我在 Rust 用户邮件中询问的,我将其清理并带到这里以供未来的 Rustaceans 使用。

【讨论】:

以上是关于当其中一个是本地引用时,如何为类型约束中的引用编写生命周期?的主要内容,如果未能解决你的问题,请参考以下文章

如何为指针引用定义 SWIG 类型映射?

如何为本地引用的节点模块指定 node_modules 文件夹

如何为引用自身的案例类提供 JsonFormats?

如何为本地通知界面编写适当的测试?

如何为graphql类型的字段对象添加排序,引用不同的graphql类型?

如何为自引用数据层次结构创建 graphql 模式?