2016-07-10 52 views
3

我在Rust Rust中有一个固定大小的数组,我想将它变成(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

最后,我想我有点过分热衷于尝试优化克隆的调用。这个问题中的一段代码每次程序运行只调用一次,它只有两个(可能很小)的字符串。 – Apanatshka

回答

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不会让你有一个“部分有效”的数组。此路径中没有涉及副本或分配。

在另一个路径中,我们必须手动将元素拉出矢量。再次,您不能通过索引将值从容器中移出(这实际上是整个索引的限制)。相反,我使用Vec::drain将前两个元素从矢量中剔除,然后从生成的迭代器中提取它们。要清楚:此路径不涉及任何副本或分配,或者

顺便说一句,那些expect方法不应永远被触发(因为drain做边界检查),但比抱歉更好的偏执;如果你想用unwrap()来代替它们,那应该没问题。

+0

这正是我一直在寻找:)对不起,在问题中的模糊性。 – Apanatshka

+0

@Apanatshka:要清楚,示例中的任何分支都不涉及复制或分配;它*纯粹*移动(并在第一个分支中为空值)。只是想澄清,因为你对你的问题的评论可能暗示你认为没有复制就没有办法做到这一点。 –

+0

我明白,你的例子不会做任何复制(但它确实分配新(空)'字符串的权利?)。我只是决定,在这种情况下,调用'clone'是好的,而且稍微不费力地编写和读取:) – Apanatshka