gpt4 book ai didi

reference - 如何使用 `AsRef` 参数?

转载 作者:行者123 更新时间:2023-11-29 08:08:15 25 4
gpt4 key购买 nike

我很难获得 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)),
}
}

函数extendPath 一起工作引用,但我想将其概括为接受 AsRef<Path> 类型的参数例如,为了也允许字符串。

我的第一次尝试,extend1extend2 , 不要通过借用检查器,它会提示 x 的生命周期在这两种情况下。

我的第三次尝试,extend3 , 有效,但有明显的代码重复缺点,随着函数体的增长,这种缺点会变得更加严重。

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

最佳答案

Option::map消耗内在值(value)(如果有的话)。所以在代码中 q.map(|x| x.as_ref()) ,闭包需要 x按值(value)。您可以通过注意 q.map(|x: &Q| x.as_ref()) 来检查这一点给出类型错误,而 q.map(|x: Q| x.as_ref())不会(它仍然会给出生命周期错误)。这意味着当您调用 x.as_ref() ,将创建对 x 的新引用,与任何外部引用无关。这意味着引用仅在闭包内部有效,但您想在 extend1 的其余部分使用它.

你想做的是借用 qextend1 结束前有效. q的借用可以使用 Option::as_ref() 转换为借用其内容(如果有的话)转换 &Option<Q>进入Option<&Q> (简单地使用 q.as_ref() 将创建您需要的 q 的借用)。那么当你使用 map 时,闭包将花费 &Q , 而不是 Q .引用的生命周期将与 q 的外部借用相同, 所以它将持续到 extend1 结束(如果需要的话)。

const DEFAULT: &str = "lib";

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

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

(playground)

由于函数的参数仅通过引用使用,因此您可能希望仅通过引用来获取它们。这就像在每个参数中添加一个符号一样简单。

const DEFAULT: &str = "lib";

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

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

(playground)

const DEFAULT: &str = "lib";

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

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

(playground)

请注意,最后一个版本不需要调用 q.as_ref() , 自 q已经有类型 Option<&Q> .此版本最接近您的原始版本 extend功能。

关于reference - 如何使用 `AsRef` 参数?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/58138961/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com