如何在内部使用`AsRef` >>

问题描述 投票:0回答:1

[我很难使AsRef以干净的方式工作。

const DEFAULT: &str = "lib";

use std::path::{Path, PathBuf};

fn extend(p: &Path, q: Option<&Path>) -> PathBuf {
    let q: &Path = q.unwrap_or(DEFAULT.as_ref());
    p.join(q)
}

// DOES NOT COMPILE
fn extend1<P: AsRef<Path>, Q: AsRef<Path>>(p: P, q: Option<Q>) -> PathBuf {
    let q: &Path = q.map(|x| x.as_ref()).unwrap_or(DEFAULT.as_ref());
    p.as_ref().join(q)
}

// DOES NOT COMPILE
fn extend2<P: AsRef<Path>, Q: AsRef<Path>>(p: P, q: Option<Q>) -> PathBuf {
    let q: &Path = match q {
        Some(x) => x.as_ref(),
        None => DEFAULT.as_ref(),
    };
    p.as_ref().join(q)
}

fn extend3<P: AsRef<Path>, Q: AsRef<Path>>(p: P, q: Option<Q>) -> PathBuf {
    match q {
        Some(x) => p.as_ref().join(x.as_ref()),
        None => p.as_ref().join(AsRef::<Path>::as_ref(DEFAULT)),
    }
}

extend函数可与Path引用一起使用,但我想将其概括为接受AsRef<Path>类型的参数,以便例如也允许使用字符串。

[我的第一次尝试,extend1extend2没有通过借阅检查器,这两种情况都抱怨x的生存期。

我的第三次尝试,extend3,虽然有效,但是具有代码重复的明显缺点,随着功能体的增长,它会变得更加严重。

在这种情况下最好的解决方案是什么?

我很难让AsRef以一种干净的方式工作。 const默认值:&str =“ lib”;使用std :: path :: {Path,PathBuf}; fn extend(p:&Path,q:Option)-> ...

reference rust lifetime borrow-checker borrowing
1个回答
0
投票

Option::map使用内部值(如果有一个)。因此,在代码q.map(|x| x.as_ref())中,闭包按值取x。您可以通过注意q.map(|x: &Q| x.as_ref())给出类型错误,而q.map(|x: Q| x.as_ref())则没有(它仍然给出生命周期错误)来检查此情况。这意味着当您调用x.as_ref()时,将创建对x的新引用,该引用与任何外部引用都不相关。这意味着该引用仅在闭包内部有效,但您想在extend1的其余部分中使用它。

您想做的是借用q,该借用有效期至extend1结束。可以使用qOption::as_ref()的借项转换为其内容(如果有)的借项,以将&Option<Q>转换为Option<&Q>(只需使用q.as_ref()将创建您需要的q借项)。然后,当您使用map时,闭包将采用&Q,而不是Q。引用的生存期将与q的外部借用相同,因此它将持续到extend1的结尾(如果需要)。

© www.soinside.com 2019 - 2024. All rights reserved.