gpt4 book ai didi

rust - 无法编译允许将值插入其中的 OneOrMany 枚举

转载 作者:行者123 更新时间:2023-11-29 08:12:27 24 4
gpt4 key购买 nike

我正在尝试创建一个枚举,它可以包含零个、一个或多个值(某种程度上是经典的)并且我将通过单个 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 valueNone ,然后再填回去:

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/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com