首页 > 解决方案 > if else 借入时临时价值下降

问题描述

我正在使用 Rusqlite,它可以让你做这样的查询:

statement.query_row(params!([1, 2, 3]), ...);

params!()定义如下:

macro_rules! params {
    () => {
        $crate::NO_PARAMS
    };
    ($($param:expr),+ $(,)?) => {
        &[$(&$param as &dyn $crate::ToSql),+] as &[&dyn $crate::ToSql]
    };
}

这很好用,但在某些情况下,我想做这样的事情:

statement.query_row(if x { params![1, 2, 3] } else { params![4, 5] }, ...

不幸的是它不起作用 - 你得到一个temporary value dropped while borrowed错误。我将问题简化为(操场):

fn main() {
    foo(&[&1, &2, &3]); // Fine!

    let x = 1;
    let y = true;
    
    let a = if y {
        &[&x, &2, &3]
    } else {
        &[&5, &6, &7]
    };
    
    foo(a); // Error
}

fn foo(_x: &[&i32]) {
}

这是有道理的,但它很烦人。我目前的解决方法基本上是这样的:

let params_a = params![1, 2, 3];
let params_b = params![4, 5];
statement.query_row(if x { params_a } else { params_b }, ...

但这有点糟糕。有没有更好的办法?

标签: rust

解决方案


在 Rust 中,需要创建一个新绑定来延长临时对象的生命周期是很常见的。您的解决方案可能是最好的方法。

板条箱的创造者rusqlite显然没有预料到这种用法——而且他们并没有让它变得容易。您可以创建自己的宏来封装值而不是返回引用,但这似乎并不值得。

您也可以将调用移动statement.query_row到条件块中:

if x {
    statement.query_row(params![1, 2, 3]); 
} else {
    statement.query_row(params![4, 5]);
}

这将避免创建您不需要的参数对象。


推荐阅读