我试图创建一个可以包含零个,一个或多个值(不知何故经典)的枚举,并通过单个push(new_value:T)
方法与之交互。它可以具有None
值(空),One
值或Many
值(基本上是矢量/切片)。
我试图为灵活类型创建一个包装器,它可以是单个值,也可以是矢量。
这是我写的但是我无法编译
enum NoneOneOrMany<T> {
None,
One(T),
Many(Vec<T>),
}
struct FormValues<T> {
value: NoneOneOrMany<T>,
}
impl<T> FormValues<T> {
pub fn new() -> FormValues<T> {
FormValues { value: NoneOneOrMany::None }
}
pub fn push(&mut self, new_value: T) {
match self.value {
NoneOneOrMany::None => self.value = NoneOneOrMany::One(new_value),
NoneOneOrMany::One(existing_value) => {
let mut vec = Vec::<T>::new();
vec.push(existing_value);
vec.push(new_value);
self.value = NoneOneOrMany::Many(vec);
}
NoneOneOrMany::Many(ref mut vec) => {
vec.push(new_value);
}
}
}
}
错误:
error[E0507]: cannot move out of borrowed content
--> src/main.rs:17:15
|
17 | match self.value {
| ^^^^ cannot move out of borrowed content
18 | NoneOneOrMany::None => self.value = NoneOneOrMany::One(new_value),
19 | NoneOneOrMany::One(existing_value) => {
| -------------- hint: to prevent move, use `ref existing_value` or `ref mut existing_value`
我的总体意图是能够做到这样的事情:
fn print_form_value<T: Debug>(x: FormValues<T>) {
match x.value {
NoneOneOrMany::None => println!("Empty"),
NoneOneOrMany::One(val) => println!("Holds one value => {:?}", val),
NoneOneOrMany::Many(vec) => println!("Holds several values => {:?}", vec),
}
}
fn test_oneOrMany() {
let mut x = FormValues::<u32>::new();
x.push(1);
x.push(2);
let mut y = FormValues::<u32>::new();
y.push(3);
let mut z = FormValues::<u32>::new();
print_form_value(x);
print_form_value(y);
print_form_value(z);
}
这可能是一个愚蠢的经典借用问题,但我刚开始使用Rust。有没有办法让我move
existing_value
从它当前拥有Option
到一个向量而不必克隆它?
答案 0 :(得分:4)
您可以暂时replace
使用value
None
移出旧值,然后稍后填写:
pub fn push(&mut self, new_value: T) {
let old_value = replace(&mut self.value, NoneOneOrMany::None);
self.value = match old_value {
NoneOneOrMany::None => {
NoneOneOrMany::One(new_value)
}
NoneOneOrMany::One(existing_value) => {
NoneOneOrMany::Many(vec![existing_value, new_value])
}
NoneOneOrMany::Many(mut vec) => {
vec.push(new_value);
NoneOneOrMany::Many(vec)
}
}
}
您不需要.clone()
,但这会导致T从self.value
额外移动到old_value
请考虑使用smallvec
包。 FormValues<T>
类型相当于SmallVec<[T; 1]>
。它也是用精心设计的unsafe code编写的,因此不需要进行不必要的移动。