我正在尝试创建一个枚举,它可以包含零个、一个或多个值(某种程度上是经典的)并且我将通过单个 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
到一个向量中,而不必克隆它?
最佳答案
您可以暂时移出旧值 replace
-ing 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
crate 代替。 FormValues<T>
类型相当于 SmallVec<[T; 1]>
.也是精心编写的unsafe code这样就不需要不必要的移动。
关于rust - 无法编译允许将值插入其中的 OneOrMany 枚举,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/43817631/