如何从Box <dyn AsRef <Path >>中提取impl AsRef <Path>值?

时间:2020-04-08 00:20:31

标签: rust traits

我正在使用std::fs中的函数,这些函数带有诸如path: impl AsRef<Path>之类的参数。我希望使自己的函数具有多态性,以便它们也可以采用任何impl AsRef<Path>而不是仅接受&str。但是,所讨论的类似路径的对象必须存储在我的一个结构中。这意味着必须将其存储为Box<dyn AsRef<Path>>才能获得已知大小。我正在努力将这个装箱的值转换为std::fs函数可以接受的任何值。

考虑以下代码:

use std::path::Path;

fn main() {
    fn polymorphic(_: impl AsRef<Path>) {}

    let boxed: Box<dyn AsRef<Path>> = Box::new("/foo/bar");
    polymorphic(/*???*/);
}

如何用问号代替问号,以便我可以用polymorphic来呼叫"/foo/bar"

1 个答案:

答案 0 :(得分:4)

取消引用并重新引用Box

use std::path::Path;

fn main() {
    fn polymorphic(_: impl AsRef<Path>) {}

    let boxed: Box<dyn AsRef<Path>> = Box::new("/foo/bar");
    polymorphic(&*boxed);
}

这意味着它必须存储为Box<dyn AsRef<Path>>

不,不是。 Path状态的文档(强调我的观点):

这是一个无大小的类型,意味着必须始终在诸如&Box之类的指针后面使用它。 有关此类型的拥有版本,请参见PathBuf

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

fn polymorphic(_: impl AsRef<Path>) {}

struct Example(PathBuf);

impl Example {
    fn new(path: impl AsRef<Path>) -> Self {
        Self(path.as_ref().to_owned())
    }

    fn example(&self) {
        polymorphic(&self.0)
    }
}

我实际上会自己使用Into<PathBuf>,因为这可以使某人将不再需要的东西授予我所有权:

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

fn polymorphic(_: impl AsRef<Path>) {}

struct Example(PathBuf);

impl Example {
    fn new(path: impl Into<PathBuf>) -> Self {
        Self(path.into())
    }

    fn example(&self) {
        polymorphic(&self.0)
    }
}