定义在引用上定义的 Index 的子特征

Define a subtrait of Index defined on a reference

我想为具体的引用类型定义一个特征,它是 std::ops::Index 的子特征,例如像这样:

trait RefIndex<'a>: Index<&'a usize> {}

然而,当我尝试像这样使用它时,我可以做到:

fn get_sum<'a>(inp: impl RefIndex<'a, Output = u64>) -> u64 {
    let mut sum = 0;
    for i in 0..1 {
        sum += inp[&i];
    }
    sum
}

我明白了

5 | fn get_sum<'a>(inp: impl RefIndex<'a, Output = u64>) -> u64 {
  |            -- lifetime `'a` defined here
...
8 |         sum += inp[&i];
  |                    ^^
  |                    |
  |                    borrowed value does not live long enough
  |                    requires that `i` is borrowed for `'a`
9 |     }
  |     - `i` dropped here while still borrowed

我认为这表明 rust 认为 Index 的实现仅对寿命与 get_sum 一样长的引用有效,而实际上我只希望在函数调用的短暂生命周期内使用它。但是,我不确定如何以将其定义为适当生命周期的方式注释 RefIndex(或 get_sum)。

请注意,对于具体类型,此问题不会发生,Rust 能够推断出引用的生命周期缩短,并且以下编译正常:

struct MyVec<T>(Vec<T>);

impl<T> Index<&usize> for MyVec<T> {
    type Output = T;

    fn index(&self, ind: &usize) -> &T {
        &self.0[*ind]
    }
}

fn get_sum_vec(inp: MyVec<u64>) -> u64 {
    let mut sum = 0;
    for i in 0..1 {
        sum += inp[&i];
    }
    sum
}

Filipe Rodrigues 在上面回答:

RefIndex 需要一个明确的生命周期参数,但将其声明为函数作用域的一部分会不必要地将其限制得太宽。通过使用 语法,它可以更窄地绑定,这很有效。

fn get_sum(inp: impl for<'a> RefIndex<'a, Output = u64>) -> u64 {
    let mut sum = 0;
    for i in 0..1 {
        sum += inp[&i];
    }
    sum
}

我之前不知道 for 语法。