如何从结构体中预定义的“范围”中访问切片?

3

使用切片语法访问切片很简单:slice = vector[i..j]

但如果范围是存储的,则无法执行以下操作:

struct StructWithRange {
    range: std::ops::Range<usize>,
}

fn test_slice(s: &StructWithRange, vector: &Vec<i32>) {
    let slice = &vector[s.range];
    println!("{:?}", slice); // prints [2, 3]
}

fn main() {
    let vector = vec![1,2,3,4,5];
    let s = StructWithRange {
        range: 1..3
    };

    test_slice(&s, &vector);
}

这会出现错误:
error[E0507]: cannot move out of borrowed content
 --> src/main.rs:6:25
  |
6 |     let slice = &vector[s.range];
  |                         ^ cannot move out of borrowed content

有没有一种方法可以在不扩展范围的情况下获取范围的切片?
例如:vector[s.range.start..s.range.end]

如果结构体中的usize可以用于索引查找,为什么不能以同样的方式使用Range<usize>


请提供一个 [MCVE],因为仅凭代码就难以理解可能出错的地方。这个MCVE还应包括编译器报告的错误信息。 - Matthieu M.
2个回答

5

由于Index是一个需要以下函数的特质:

fn index(&self, index: Idx) -> &Self::Output

它消耗/移动用于索引的值 (index)。在您的情况下,您正在尝试使用从借用的结构中获得的Range对切片进行索引,但由于您仅传递了一个引用且该范围并未实现Copy,因此此操作失败了。
您可以通过改变test_slice的定义以消耗StructWithRangeclone()索引中的s.range来修复它。

4
错误信息出现是因为Range没有实现Copy,并且Index消耗了它的索引。
通过添加一个调用.clone()可以解决问题:&vector[s.range.clone()]
如果你检查代码,它链接到被拒绝的建议,在这种情况下将Copy添加到Range中,并且它的参数是Copy在这里
拒绝原因是:

These don't have it because they're iterators.

The choice of removing Copy impls instead of adjusted for loop desugaring or linting was made to prevent this problematic case:

let mut iter = 0..n;
for i in iter { if i > 2 { break; } }
iter.collect()

Here iter is actually not mutated, but copied. for i in &mut iter is required to mutate the iterator.

We could switch to linting against using an iterator variable after it was copied by a for loop, but there was no decision towards that.


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接