Generics 为什么可以';t不能克隆通用选项<;T>;当T不';不实施克隆?

Generics 为什么可以';t不能克隆通用选项<;T>;当T不';不实施克隆?,generics,rust,clone,Generics,Rust,Clone,给定一个带有泛型选项的结构,其中T可能无法实现Clone为什么不能克隆None?类型为t的None不是与任何其他None相同吗?例如: struct Foo<T> { bar: Vec<Option<T>>, } impl <T> Foo<T> { fn blank(size: usize) -> Foo<T> { Foo { bar: vec![None; s

给定一个带有泛型
选项的结构,其中
T
可能无法实现
Clone
为什么不能克隆
None
?类型为
t
None
不是与任何其他
None
相同吗?例如:

struct Foo<T> {
    bar: Vec<Option<T>>,
}

impl <T> Foo<T> {
    fn blank(size: usize) -> Foo<T> {
        Foo {
            bar: vec![None; size],
        }
    }
}
structfoo{
酒吧:Vec,
}
impl-Foo{
fn空白(尺寸:usize)->Foo{
福{
条形图:vec![无;大小],
}
}
}

如果一个部件不能克隆,那么就不能克隆任何部件。从类型的角度考虑这一点:您有一个名为
foo
的变量,其类型为
Option
,其中
T
是不可克隆的。当然,
None
可以克隆,但是
Some()
不能克隆,并且变量的类型不会告诉您它是哪个。因此,从编译时的角度来看,您不能克隆该选项。

只有当内部
t
实现
克隆时,
选项才能克隆:

let bar = std::iter::repeat_with(|| Option::<T>::None).take(size).collect::<Vec<_>>();
impl克隆选项
哪里
T:克隆,
类型为
t
None
不是与任何其他
None
相同吗

实际上,不是。Rust编译器甚至不将
None
视为一个类型。相反,
None
只是
选项
的一个变体(子类型)。尝试比较两个不同的
T
s的
None
s:

设a:Option=None;
设b:Option=None;
断言!(a、b)
您将看到它们实际上是完全不相关的类型:

错误[E0308]:类型不匹配
-->src/main.rs:4:5
|
4 |断言| eq!(a、b)
|^^^^^^^^^^^^^^^^^^^^^^^^应为结构“String”,找到“u8”`
|
=注意:应为enum`选项`
找到enum`选项`
因此,Rust编译器实际上将
None
视为
选项:::None
。这意味着如果
T
不是
Clone
,那么
选项
就不是
Clone
,因此
选项:::None
不能是
Clone

要使代码编译,必须将
T
约束为
Clone

let bar = std::iter::repeat_with(|| Option::<T>::None).take(size).collect::<Vec<_>>();
structfoo{
酒吧:Vec,
}
impl-Foo{
fn空白(尺寸:usize)->Foo{
福{
条形图:vec![无;大小],
}
}
}

现在编译器知道
T
Clone
,并且
选项
Clone
(和
选项::::无
)的实现已经完成。

其他答案正确地指出了ouf,这是由于
vec的方式-宏已实现。您可以手动创建任何
选项的
Vec
,而无需
T
成为
Clone

let bar = std::iter::repeat_with(|| Option::<T>::None).take(size).collect::<Vec<_>>();
let bar=std::iter::使用(| |选项::::无)重复_)。获取(大小)。收集::();
这将创建
大小
-选项编号:::无
,并将它们放置在
Vec
中,该Vec将预先分配到适当的大小。这适用于任何
T

类型为
t
None
不是与任何其他
None
相同吗

绝对不是!与基于引用的语言不同,在基于引用的语言中,null通常被实现为null引用,而Rust的
选项
不引入间接寻址,当选项为
Some
时,它将
T
内联存储。由于所有枚举变量都具有相同的大小,
None
变量必须至少占用与
T
相同的空间

话虽如此,从技术上讲,
None
值可以在
T
不为
Clone
的情况下克隆,这是正确的,因为枚举的
None
变量不包含
T
,它仅存储鉴别器,并保留可能包含
T
的空间(如果变量更改为
Some
)。但是,由于Rust枚举变量不是单独的类型,因此为枚举定义的特征绑定必须覆盖所有变量


参见其他答案更详细的解释和说明如何创建不可克隆的
选项的
None
值的向量

“类型
t
None
与任何其他
None
相同吗?”-不,
None
选项的变体。它的全名应该是
选项:::None
,但您通常不需要它,因为类型通常是推断出来的。您链接的RFC与手头的问题没有任何关系:变体类型可能没有固有的impl,或者实现的特征。@IbraheemAhmed如果我理解正确,就没有类型理论的理由说明不能克隆
None
,但是静态分析器还没有这个功能。正确吗?@HiDefender好吧,类型理论的原因是枚举变量实际上不是类型。相反,它们是枚举的变体(子类型),其行为由包含它们的枚举决定。Rust编译器查看枚举变量的方式将来可能会改变,也可能不会改变。@HiDefender我更新了我的问题,使之更清楚。@Shepmaster更新了。补充说明:您只需使用
repeat_with(| | None)
,它是一个
选项,可以推断出
。为了清楚起见。