重写函数以接受 AsRef<Path> 而不是 &Path
Rewriting a function to accept AsRef<Path> instead of &Path
如何编写以下函数来不仅接受 Path
,而且接受 String
或 &str
?
fn find_database1<'a>(path: &'a Path) -> Option<&'a Path> {
path.parent()
}
写完上面提到的函数后,我想把它转换成一种形式,不仅可以接受Path
,还可以接受String
或&str
。我最终得到了以下两个版本,每个版本都不起作用。函数 find_database3
试图更好地理解原因,但遗憾的是我不明白为什么它不起作用。
fn find_database2<'a, P>(path: P) -> Option<&'a Path>
where
P: 'a + AsRef<Path>,
{
path.as_ref().parent()
}
fn find_database3<'a, P>(path: P) -> Option<&'a Path>
where
P: 'a + AsRef<Path>,
{
let _path: &'a Path = path.as_ref();
_path.parent()
}
这些是我得到的错误:
error[E0515]: cannot return value referencing function parameter `path`
--> src/main.rs:11:5
|
11 | path.as_ref().parent()
| ----^^^^^^^^^^^^^^^^^^
| |
| returns a value referencing data owned by the current function
| `path` is borrowed here
error[E0597]: `path` does not live long enough
--> src/main.rs:18:27
|
14 | fn find_database3<'a, P>(path: P) -> Option<&'a Path>
| -- lifetime `'a` defined here
...
18 | let _path: &'a Path = path.as_ref();
| -------- ^^^^ borrowed value does not live long enough
| |
| type annotation requires that `path` is borrowed for `'a`
19 | _path.parent()
20 | }
| - `path` dropped here while still borrowed
use std::path::Path;
fn main() {
let path_str: &str = "root/path";
let path_string: String = path_str.to_string();
let path_path: &Path = &Path::new(path_str);
let root = find_database1(path_path);
println!("{:?}", root);
find_database2(path_str);
find_database2(path_string);
let root = find_database2(path_path);
println!("{:?}", root);
}
Path::parent
有这个签名:
fn parent(&self) -> Option<&Path>;
因此返回的结果包含对调用者拥有的某些数据的引用。您不能在 String
上调用 parent()
然后删除 String
,因为这会使 parent()
返回的引用无效。如果您放宽接受 String
s 而接受 &String
s 的要求,则可以使您的功能正常工作。示例:
use std::path::Path;
// takes &str, &String, or &Path
fn find_database2<'a, P>(path: &'a P) -> Option<&'a Path>
where P: 'a + ?Sized + AsRef<Path>,
{
path.as_ref().parent()
}
fn main() {
let path_str: &str = "root/path";
let path_string: String = path_str.to_string();
let path_path: &Path = &Path::new(path_str);
find_database2(path_str); // &str
find_database2(&path_string); // &String
let root = find_database2(path_path); // &Path
println!("{:?}", root);
}
另一方面,如果您真的想接受 String
,您可以在函数体内将 Option<&Path>
转换为 Option<PathBuf>
。这是有效的,因为 PathBuf
是 Path
:
的拥有版本
use std::path::{Path, PathBuf};
// takes &str, &String, String, &Path, or PathBuf
fn find_database2<'a, P>(path: P) -> Option<PathBuf>
where P: 'a + AsRef<Path>,
{
path.as_ref().parent().map(|path| {
let mut path_buf = PathBuf::new();
path_buf.push(path);
path_buf
})
}
fn main() {
let path_str: &str = "root/path";
let path_string: String = path_str.to_string();
let path_path: &Path = &Path::new(path_str);
find_database2(path_str); // &str
find_database2(&path_string); // &String
find_database2(path_string); // String
let root = find_database2(path_path); // &Path
println!("{:?}", root);
}
如何编写以下函数来不仅接受 Path
,而且接受 String
或 &str
?
fn find_database1<'a>(path: &'a Path) -> Option<&'a Path> {
path.parent()
}
写完上面提到的函数后,我想把它转换成一种形式,不仅可以接受Path
,还可以接受String
或&str
。我最终得到了以下两个版本,每个版本都不起作用。函数 find_database3
试图更好地理解原因,但遗憾的是我不明白为什么它不起作用。
fn find_database2<'a, P>(path: P) -> Option<&'a Path>
where
P: 'a + AsRef<Path>,
{
path.as_ref().parent()
}
fn find_database3<'a, P>(path: P) -> Option<&'a Path>
where
P: 'a + AsRef<Path>,
{
let _path: &'a Path = path.as_ref();
_path.parent()
}
这些是我得到的错误:
error[E0515]: cannot return value referencing function parameter `path`
--> src/main.rs:11:5
|
11 | path.as_ref().parent()
| ----^^^^^^^^^^^^^^^^^^
| |
| returns a value referencing data owned by the current function
| `path` is borrowed here
error[E0597]: `path` does not live long enough
--> src/main.rs:18:27
|
14 | fn find_database3<'a, P>(path: P) -> Option<&'a Path>
| -- lifetime `'a` defined here
...
18 | let _path: &'a Path = path.as_ref();
| -------- ^^^^ borrowed value does not live long enough
| |
| type annotation requires that `path` is borrowed for `'a`
19 | _path.parent()
20 | }
| - `path` dropped here while still borrowed
use std::path::Path;
fn main() {
let path_str: &str = "root/path";
let path_string: String = path_str.to_string();
let path_path: &Path = &Path::new(path_str);
let root = find_database1(path_path);
println!("{:?}", root);
find_database2(path_str);
find_database2(path_string);
let root = find_database2(path_path);
println!("{:?}", root);
}
Path::parent
有这个签名:
fn parent(&self) -> Option<&Path>;
因此返回的结果包含对调用者拥有的某些数据的引用。您不能在 String
上调用 parent()
然后删除 String
,因为这会使 parent()
返回的引用无效。如果您放宽接受 String
s 而接受 &String
s 的要求,则可以使您的功能正常工作。示例:
use std::path::Path;
// takes &str, &String, or &Path
fn find_database2<'a, P>(path: &'a P) -> Option<&'a Path>
where P: 'a + ?Sized + AsRef<Path>,
{
path.as_ref().parent()
}
fn main() {
let path_str: &str = "root/path";
let path_string: String = path_str.to_string();
let path_path: &Path = &Path::new(path_str);
find_database2(path_str); // &str
find_database2(&path_string); // &String
let root = find_database2(path_path); // &Path
println!("{:?}", root);
}
另一方面,如果您真的想接受 String
,您可以在函数体内将 Option<&Path>
转换为 Option<PathBuf>
。这是有效的,因为 PathBuf
是 Path
:
use std::path::{Path, PathBuf};
// takes &str, &String, String, &Path, or PathBuf
fn find_database2<'a, P>(path: P) -> Option<PathBuf>
where P: 'a + AsRef<Path>,
{
path.as_ref().parent().map(|path| {
let mut path_buf = PathBuf::new();
path_buf.push(path);
path_buf
})
}
fn main() {
let path_str: &str = "root/path";
let path_string: String = path_str.to_string();
let path_path: &Path = &Path::new(path_str);
find_database2(path_str); // &str
find_database2(&path_string); // &String
find_database2(path_string); // String
let root = find_database2(path_path); // &Path
println!("{:?}", root);
}