使用Add trait时简化Rust扩展trait寿命



我需要实现AsRef<[T]>的所有东西的扩展特性。这种特性的方法引用T,并基于一些数学运算返回原始数组的子切片。

示例代码可能看起来像:

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]
}
}

不过,它并不编译。

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`

我真的不明白为什么element的寿命必须大于'a

不管怎样,过了一段时间,我让它发挥了作用,但感觉不对。

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]
}
}

根据我的需要,有可能简化这个例子的终身管理吗?

您的终身问题源于绑定的&'a T: Add<Output = T>。这意味着&T实现Add,但仅当生存期恰好为&'a T。您最可能想要的是for<'a> &'a T: Add<Output = T>,它指定&T在您选择的任何生存期内实现Add。(1(

通过此更改,您可以在不需要指定更多生存期的情况下编译示例代码。游戏场

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(严格来说,这是一个更具限制性的界限,但我很难看到第一个界限得到满足而第二个界限没有得到满足的情况。

最新更新