2016-11-17 22 views
1

由於可以將可變引用傳遞給一個向量(不會引起移動),因此可以多次將Option<reference>函數傳遞給函數,而不會導致借用檢查錯誤?如何將`Option <&mut ...>`傳遞給多個函數調用而不會導致移動錯誤?

這個簡單的例子只是顯示了當Option<&mut Vec<usize>>傳遞多次到功能會發生什麼:

fn maybe_push(mut v_option: Option<&mut Vec<usize>>) -> usize { 
    let mut c = 0; 
    if let Some(ref mut v) = v_option.as_mut() { 
     for i in 0..10 { 
      v.push(i); 
      c += i; 
     } 
    } 

    return c; 
} 

fn maybe_push_multi(v_option: Option<&mut Vec<usize>>) -> usize { 
    let mut c = 0; 
    c += maybe_push(v_option); 
    c += maybe_push(v_option); 
    c += maybe_push(None); 
    return c; 
} 

fn main() { 
    let mut v: Vec<usize> = vec![]; 
    let v_option = Some(&mut v); 
    println!("{}", maybe_push_multi(v_option)); 
} 

Playground

給出了錯誤:

error[E0382]: use of moved value: `v_option` 
    --> <anon>:17:21 
    | 
16 |  c += maybe_push(v_option); 
    |      -------- value moved here 
17 |  c += maybe_push(v_option); 
    |      ^^^^^^^^ value used here after move 
    | 
    = note: move occurs because `v_option` has type `std::option::Option<&mut std::vec::Vec<usize>>`, which does not implement the `Copy` trait 

回答

4

可以傳遞Option也可以參考,如果你不想讓它進入函數。

fn maybe_push(mut v_option: &mut Option<&mut Vec<usize>>) -> usize 

// ... 

maybe_push_twice(&mut v_option); 

然後更換:

maybe_push(None); 

有了:

maybe_push(&mut None); 
2

您可以用match表達解構的Option,然後功能maybe_push()的每個調用創建一個新的Option值:

fn maybe_push_twice(v_option: Option<&mut Vec<usize>>) -> usize { 
    let mut c = 0; 
    match v_option { 
     Some(v) => { 
      c += maybe_push(Some(v)); 
      c += maybe_push(Some(v)); 
     } 
     None => { 
      c += maybe_push(None); 
      c += maybe_push(None);   
     } 
    }; 
    return c; 
} 

這裏是一個更方便的方法:

fn maybe_push_twice(mut v_option: Option<&mut Vec<usize>>) -> usize { 
    let mut c = 0; 
    c += maybe_push(v_option.as_mut().map(|x| &mut **x)); 
    c += maybe_push(v_option); 
    return c; 
} 

您可以使用,而不是一個宏觀的性狀:

trait RefMut<T> { 
    fn ref_mut(&mut self) -> Option<&mut T>; 
} 

impl<'t, T> RefMut<T> for Option<&'t mut T>{ 
    #[inline] 
    fn ref_mut(&mut self) -> Option<&mut T>{ 
     self.as_mut().map(|x| &mut**x) 
    } 
} 

fn maybe_push_twice(mut v_option: Option<&mut Vec<usize>>) -> usize { 
    let mut c = 0; 
    c += maybe_push(v_option.ref_mut()); 
    c += maybe_push(v_option); 
    return c; 
} 
+0

好知道作爲替代現有的答案。雖然有效,但這使得在多次向函數傳遞參數時使用它變得很煩人。我試圖將'opt.as_mut()。map(| x |&mut ** x)'放入宏中。 – ideasman42

相關問題