我有一个固定大小的String
s:[String; 2]
数组。我想把它变成(String, String)
。我可以不复制值吗?
我正在处理的一段代码如下:
let (basis, names_0, names_1) = if let Some(names) = self.arg_name {
(ComparisonBasis::Name, names[0], names[1])
} else {
(ComparisonBasis::File, self.arg_file[0], self.arg_file[1])
};
类型:
self.arg_name: Option<[String; 2]>
self.arg_file: Vec<String>
现在我收到错误
cannot move out of type `[std::string::String; 2]`, a non-copy fixed-size array [E0508]
和
cannot move out of indexed content [E0507]
表示if
答案 0 :(得分:4)
您已经省略了相当多的背景,因此我在几个方面进行了猜测。我也会更接近你问的问题,而不是你的片段隐含的模糊。
struct NeverSpecified {
arg_names: Option<[String; 2]>,
arg_file: Vec<String>,
}
impl NeverSpecified {
fn some_method_i_guess(mut self) -> (String, String) {
if let Some(mut names) = self.arg_names {
use std::mem::replace;
let name_0 = replace(&mut names[0], String::new());
let name_1 = replace(&mut names[1], String::new());
(name_0, name_1)
} else {
let mut names = self.arg_file.drain(0..2);
let name_0 = names.next().expect("expected 2 names, got 0");
let name_1 = names.next().expect("expected 2 names, got 1");
(name_0, name_1)
}
}
}
我使用std::mem::replace
来切换数组的内容,同时使其保持有效状态。这是必要的,因为Rust不会让你有一个部分有效的&#34;阵列。此路径中没有涉及副本或分配。
在另一条路径中,我们必须手动将元素从向量中拉出来。同样,您不能仅通过索引将值移出容器(这实际上是整体索引的限制)。相反,我使用Vec::drain
基本上切掉了向量中的前两个元素,然后从生成的迭代器中提取它们。要明确:此路径不涉及任何副本或分配, 。
顺便说一句,那些expect
方法不应该被触发(因为drain
确实需要检查),但是更好的偏执而不是抱歉;如果你想用unwrap()
来代替它们,那应该没问题。
答案 1 :(得分:1)
如果您愿意使用夜间功能,可以使用切片模式一次绑定到数组的所有值:
#![feature(slice_patterns)]
struct NeverSpecified {
arg_names: Option<[String; 2]>,
arg_file: Vec<String>,
}
impl NeverSpecified {
fn some_method_i_guess(mut self) -> (String, String) {
if let Some([name_0, name_1]) = self.arg_names.take() {
(name_0, name_1)
} else {
let mut names = self.arg_file.drain(0..2);
let name_0 = names.next().expect("expected 2 names, got 0");
let name_1 = names.next().expect("expected 2 names, got 1");
(name_0, name_1)
}
}
}