简体   繁体   English

使用 Add trait 时简化 Rust extension trait lifetimes

[英]Simplify Rust extension trait lifetimes when using Add trait

I need an extension trait for everything that implements AsRef<[T]> .对于实现AsRef<[T]>的所有内容,我都需要一个扩展特征。 A method of this trait takes a reference to T and based on some math with it returns a sub-slice of the original array.此特征的方法采用对T的引用,并基于一些数学运算返回原始数组的子切片。

Sample code can look like:示例代码如下所示:

trait Sample<T> {
    fn sample(&self, element: &T, k: usize) -> &[T];
}

impl<'a, A, T> Sample<T> for A
where
    A: AsRef<[T]>,
    &'a T: Add<Output = T>,
    T: 'a,
{
    fn sample(&self, element: &T, k: usize) -> &[T] {
        let array = self.as_ref();
        let doubled = element + element;
        &array[0..0]
    }
}

It does not compile, though.但是,它不编译。

error: lifetime may not live long enough
  --> src/arrays/sample.rs:15:23
   |
7  | impl<'a, A, T> Sample<T> for A
   |      -- lifetime `'a` defined here
...
13 |     fn sample(&self, element: &T, k: usize) -> &[T] {
   |                               - let's call the lifetime of this reference `'1`
14 |         let array = self.as_ref();
15 |         let doubled = element + element;
   |                       ^^^^^^^^^^^^^^^^^ requires that `'1` must outlive `'a`

I don't really understand why element lifetime must be bigger than 'a .我真的不明白为什么element生命周期必须大于'a

Anyways, after a while I made it work, but it does not feel right.无论如何,过了一会儿我让它工作了,但感觉不对。

use core::ops::Add;

trait KClosestExt<'t, T> {
    fn find_k_closest(&'t self, element: &'t T, k: usize) -> &[T];
}

impl<'a, 't, A, T> KClosestExt<'t, T> for A
where
    A: AsRef<[T]>,
    &'a T: Add<Output = T>,
    T: 'a + 't + PartialOrd,
    't: 'a,
{
    fn find_k_closest(&'t self, element: &'t T, k: usize) -> &[T] {
        let array = self.as_ref();
        if k > array.len() {
            return array;
        }

        let doubled = element + element;
        let left = binary_search(0, array.len() - k, |mid| doubled > &array[mid + k] + &array[mid]);
        &array[left..left + k]
    }
}

According to what I need, is it possible to simplify lifetime management for this example?根据我的需要,是否可以简化此示例的生命周期管理?

Your lifetime issues stem from the bound &'a T: Add<Output = T> .您一生的问题源于绑定&'a T: Add<Output = T> This says that &T implements Add but only when the lifetime is exactly &'a T .这表示&T实现Add但仅当生命周期恰好&'a T时。 What you most likely want is for<'a> &'a T: Add<Output = T> which specifies that &T implements Add for any lifetime that you choose.您最可能想要的是for<'a> &'a T: Add<Output = T> ,它指定&T在您选择的任何生命周期内实现Add (1) (1)

With this change, you sample code compiles without needing to specify any more lifetimes.通过此更改,您可以编译示例代码而无需指定更多生命周期。 playground . 游乐场

trait Sample<T> {
    fn sample(&self, element: &T, k: usize) -> &[T];
}

impl<A, T> Sample<T> for A
where
    A: AsRef<[T]>,
    for<'a> &'a T: std::ops::Add<Output = T>,
{
    fn sample(&self, element: &T, k: usize) -> &[T] {
        let array = self.as_ref();
        let doubled = element + element;
        &array[0..0]
    }
}

(1) Strictly speaking, this is a more restrictive bound but I struggle to see a situation where the first one is fulfilled but not the second one. (1) 严格来说,这是一个更严格的界限,但我很难看到第一个满足但第二个不满足的情况。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM