最近,我想为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`

显然,Range<T>永远不会实现Copy,即使TCopy,就像f32是.Why is that?我以为Range<T>就是T?那么它肯定能实现Copy

推荐答案

因为Range<T>经常用作迭代器,迭代器是Copy was discovered to be a footgun.One specific example与认为迭代器是高级的有关,而实际上迭代器是高级的副本:

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

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

Another example:

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

还有一个问题:Using the same iterator multiple times in Rust

人们认为,通过clone显式复制迭代器有助于防止这些情况


具体来说,将Copy添加到Range was proposed and rejected.有人提出了一个潜在的解决办法:

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

另见:

Rust相关问答推荐

为什么在Rust struct 中只允许最后一个字段具有动态大小的类型

收集RangeInclusive T到Vec T<><>

替换可变引用中的字符串会泄漏内存吗?

重写Rust中的方法以使用`&;mut self`而不是`mut self`

完全匹配包含大小写的整数范围(&Q;)

在铁 rust 中,如何一次只引用几件事中的一件?

不同类型泛型的映射

如何使用reqwest进行异步请求?

为什么实现特征的对象期望比具体对象有更长的生命周期?

我可以解构self 参数吗?

Rust 文件未编译到 dll 中

如何为已实现其他相关 std trait 的每个类型实现一个 std Trait

枚举的利基优化如何在 Rust 中工作?

为什么 Rust 的临时值有时有参考性有时没有?

有什么办法可以追踪泛型的单态化过程吗?

为什么 no_std crate 可以依赖于使用 std 的 crate?

如何存储返回 Future 的闭包列表并在 Rust 中的线程之间共享它?

如何在 nom 中构建负前瞻解析器?

Cargo:如何将整个目录或文件包含在功能标志中?

为什么可以从闭包中返回私有 struct