PhantomData
以令人惊讶的方式与Copy
互动:
use std::marker::PhantomData;
#[derive(Copy, Clone)]
pub struct Seconds;
pub struct Meters;
#[derive(Copy, Clone)]
pub struct Val<T> {
pub v: PhantomData<T>
}
fn main() {
let v1: Val<Seconds> = Val {v: PhantomData};
let v2 = v1;
let v3 = v1;
let v4: Val<Meters> = Val {v: PhantomData};
let v5 = v4;
let v6 = v4;
}
这失败如下:
src/main.rs:20:13: 20:15 error: use of moved value: `v4` [E0382]
src/main.rs:20 let v6 = v4;
^~
src/main.rs:19:13: 19:15 note: `v4` moved here because it has type `Val<Meters>`, which is moved by default
src/main.rs:19 let v5 = v4;
我认为为Copy
派生Val<Meters>
会给出Val<Meters>
复制语义。但显然,只有在Val
类型参数T
也实现Copy
的情况下,这才是真的。我不明白为什么。
PhantomData
始终实施Copy
,regardless of whether its type parameter does。无论如何,如果PhantomData<Meters>
没有实现Copy
,我希望编译器抱怨它无法为Copy
派生Val<Meters>
。相反,编译器愉快地为Copy
派生Val<Meters>
,但它应用了移动语义。
这种行为是故意的吗?如果是这样,为什么?
答案 0 :(得分:4)
我认为为
Val<Meters>
派生复制会给Val<Meters>
复制语义。
但Copy
并非导出Val<Meters>
,仅适用于Val<T>
本身为T
的所有Copy
。
Github上有几个未解决的问题,例如: this one。我的印象是,这不是故意的,而只是derive
目前的工作方式的限制。
您可以通过为Clone
和Copy
手动编写毛毯impl来解决此问题:
impl <T> Clone for Val<T> {
fn clone(&self) -> Val<T> {
Val {v: PhantomData}
}
}
impl <T> Copy for Val<T> {}