如何将`Option<& mut ...>`传递给多个函数调用而不会导致移动错误?

时间:2016-11-17 15:13:25

标签: rust borrow-checker

由于可以将可变引用传递给向量(不引起移动),如何将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)); } 多次传递给函数时会发生什么:

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

Playground

给出错误:

DECLARE My_Timestamp TIMESTAMP ;

SELECT from_unixtime(<source_column_name>)
  INTO My_Timestamp 
  FROM <your_table_name>
 WHERE ....

2 个答案:

答案 0 :(得分: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);

答案 1 :(得分:2)

您可以使用Option表达式对match进行解构,然后为函数Option的每次调用创建一个新的maybe_push()值:

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;
}