当 T 没有实现 Clone 时,为什么不能为通用 Option<T> 克隆 None?
Why can't None be cloned for a generic Option<T> when T doesn't implement Clone?
给定一个具有通用 Option<T>
的结构,其中 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],
}
}
}
如果一个部分不能被克隆,那么任何部分都不能被克隆。从类型的角度考虑:您有一个名为 foo
的 Option<T>
类型的变量,其中 T
不可克隆。当然,None
可以被克隆,但是 Some(_)
不能,而且变量的类型不会告诉你它是什么。因此,从编译时的角度来看,您无法克隆该选项。
仅当内部 T
实现 Clone
:
时才能克隆 Option
impl<T> Clone for Option<T>
where
T: Clone,
Isn't a None
of type T
the same as any other None
?
实际上,没有。 Rust 编译器甚至不将 None
视为一种类型。相反,None
只是 Option<T>
的变体(子类型)。尝试比较两个不同 T
的 None
:
let a: Option<String> = None;
let b: Option<u8> = None;
assert_eq!(a, b)
你会发现它们实际上是完全不相关的类型:
error[E0308]: mismatched types
--> src/main.rs:4:5
|
4 | assert_eq!(a, b)
| ^^^^^^^^^^^^^^^^ expected struct `String`, found `u8`
|
= note: expected enum `Option<String>`
found enum `Option<u8>`
所以 Rust 编译器实际上将 None
视为 Option::<T>::None
。这意味着如果 T
不是 Clone
,则 Option<T>
不是 Clone
,因此 Option::<T>::None
不能是 Clone
.
要使您的代码编译,您必须将 T
限制为 Clone
:
struct Foo<T: Clone> {
bar: Vec<Option<T>>,
}
impl <T: Clone> Foo<T> {
fn blank(size: usize) -> Foo<T> {
Foo {
bar: vec![None; size],
}
}
}
现在编译器知道T
是Clone
,Option<T>
(和Option::<T>::None
)的Clone
的实现就完成了。
正如其他答案正确指出的那样,这是由于 vec!
-宏的实现方式所致。您可以手动创建任何 Option<T>
的 Vec
,而不需要 T
为 Clone
:
let bar = std::iter::repeat_with(|| Option::<T>::None).take(size).collect::<Vec<_>>();
这将创建 size
数量的 Option::<T>::None
并将它们放置在 Vec
中,这将被预先分配到适当的大小。这适用于任何 T
.
Isn't a None
of type T
the same as any other None
?
绝对不是!与通常将 null 作为空引用实现的基于引用的语言不同,Rust 的 Option<T>
不引入间接寻址,并在选项为 Some
时内联存储 T
。由于所有枚举变体都具有相同的大小,因此 None
变体必须至少占据与 T
.
一样多的 space
话虽如此,从技术上讲,None
值可以在 T
不为 Clone
的情况下进行克隆,这在技术上是正确的,因为枚举 [=] 的 None
变体34=]不包含T
,它只存储鉴别器并保留space,可以包含T
如果变体将更改为 Some
。但是由于 Rust 枚举变体不是单独的类型,因此为枚举定义的特征边界必须涵盖所有变体。
查看其他答案更详细的解释和说明如何创建不可克隆 Option
.
的 None
值的向量
给定一个具有通用 Option<T>
的结构,其中 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],
}
}
}
如果一个部分不能被克隆,那么任何部分都不能被克隆。从类型的角度考虑:您有一个名为 foo
的 Option<T>
类型的变量,其中 T
不可克隆。当然,None
可以被克隆,但是 Some(_)
不能,而且变量的类型不会告诉你它是什么。因此,从编译时的角度来看,您无法克隆该选项。
仅当内部 T
实现 Clone
:
Option
impl<T> Clone for Option<T>
where
T: Clone,
Isn't a
None
of typeT
the same as any otherNone
?
实际上,没有。 Rust 编译器甚至不将 None
视为一种类型。相反,None
只是 Option<T>
的变体(子类型)。尝试比较两个不同 T
的 None
:
let a: Option<String> = None;
let b: Option<u8> = None;
assert_eq!(a, b)
你会发现它们实际上是完全不相关的类型:
error[E0308]: mismatched types
--> src/main.rs:4:5
|
4 | assert_eq!(a, b)
| ^^^^^^^^^^^^^^^^ expected struct `String`, found `u8`
|
= note: expected enum `Option<String>`
found enum `Option<u8>`
所以 Rust 编译器实际上将 None
视为 Option::<T>::None
。这意味着如果 T
不是 Clone
,则 Option<T>
不是 Clone
,因此 Option::<T>::None
不能是 Clone
.
要使您的代码编译,您必须将 T
限制为 Clone
:
struct Foo<T: Clone> {
bar: Vec<Option<T>>,
}
impl <T: Clone> Foo<T> {
fn blank(size: usize) -> Foo<T> {
Foo {
bar: vec![None; size],
}
}
}
现在编译器知道T
是Clone
,Option<T>
(和Option::<T>::None
)的Clone
的实现就完成了。
正如其他答案正确指出的那样,这是由于 vec!
-宏的实现方式所致。您可以手动创建任何 Option<T>
的 Vec
,而不需要 T
为 Clone
:
let bar = std::iter::repeat_with(|| Option::<T>::None).take(size).collect::<Vec<_>>();
这将创建 size
数量的 Option::<T>::None
并将它们放置在 Vec
中,这将被预先分配到适当的大小。这适用于任何 T
.
Isn't a
None
of typeT
the same as any otherNone
?
绝对不是!与通常将 null 作为空引用实现的基于引用的语言不同,Rust 的 Option<T>
不引入间接寻址,并在选项为 Some
时内联存储 T
。由于所有枚举变体都具有相同的大小,因此 None
变体必须至少占据与 T
.
话虽如此,从技术上讲,None
值可以在 T
不为 Clone
的情况下进行克隆,这在技术上是正确的,因为枚举 [=] 的 None
变体34=]不包含T
,它只存储鉴别器并保留space,可以包含T
如果变体将更改为 Some
。但是由于 Rust 枚举变体不是单独的类型,因此为枚举定义的特征边界必须涵盖所有变体。
查看其他答案更详细的解释和说明如何创建不可克隆 Option
.
None
值的向量