Как извлечь значение ImpR AsRef <Path>из коробки ? - PullRequest
1 голос
/ 08 апреля 2020

Я использую функции из std::fs, которые принимают аргументы, такие как path: impl AsRef<Path>. Я sh хочу сделать мои собственные функции полиморфными c, чтобы они тоже могли принимать любые 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 Ответ

4 голосов
/ 08 апреля 2020

Разыменование и повторная ссылка на 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)
    }
}
...