为什么即使 T 是 Copy,ops::Range<T> 也没有实现 Copy?

29

最近,我想为3D投影编写一个包含参数的类型:

use std::ops::Range;

#[derive(Clone, Copy)]
struct CamProj {
    /// Near and far plane
    proj_range: Range<f32>,
    /// Field of view
    fov: cgmath::Rad<f32>,     // `Rad` derives `Copy`
    /// Width divided by height
    aspect_ratio: f32,       
}

然而,我遇到了这个错误:
error[E0204]: the trait `Copy` may not be implemented for this type
 --> <anon>:3:21
  |
3 |     #[derive(Clone, Copy)]
  |                     ^^^^
...
6 |         proj_range: Range<f32>,
  |         ---------------------- this field does not implement `Copy`

显然,即使T是Copy类型,例如f32,Range<T>也从未实现Copy为什么呢? 我以为Range<T>只是一对T,所以它肯定可以实现Copy


2
我肯定以前看过这个问题……但是当然再也找不到了。我找到的最接近的潜在重复是https://dev59.com/ZYzda4cB1Zd3GeqPlVgM。我似乎记得它没有被实现,因为有些情况下可能会令人困惑:https://github.com/rust-lang/rust/issues/18045。 - Matthieu M.
1个回答

32

因为 Range<T> 经常被用作迭代器,而让迭代器成为 Copy 被发现是一种步枪错误一个具体的例子 是在认为迭代器已经前进时,实际上是复制品已经前进了:

for x in it {  // a *copy* of the iterator is used here
    // ..
}

match it.next() {  // the original iterator is used here
    // ..
}

另一个示例

fn main() {
    let stream = "Hello, world!".chars().cycle();
    for _ in 0..10 {
        let chunk: String = stream.take(3).collect();
        println!("{}", chunk);
    }
}

还有一个问题引发了疑问:在Rust中多次使用同一迭代器

人们认为通过clone显式地复制迭代器可以帮助防止这些情况发生


具体而言,提议并被拒绝将Copy重新添加到Range中。建议采用一种潜在的解决方法:

Range字段是公共的,您可以在构造函数/函数边界处将它们重新打包成可复制的元组(或等效物)

另请参见:


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