Как я могу реализовать метод для работы с & str, Box <str>, Rc <str>и т. Д.? - PullRequest
0 голосов
/ 22 мая 2018

У меня есть код, который каким-то образом преобразует строковую ссылку, например, принимает первую букву

trait Tr {
    fn trim_indent(self) -> Self;
}

impl<'a> Tr for &'a str {
    fn trim_indent(self) -> Self {
        &self[..1] // some transformation here
    }
}

fn main() {
    let s = "aaa".trim_indent();
    println!("{}", s);
}

Теперь я пытаюсь обобщить этот код для любого конкретного типа, который реализует AsRef<str>.Моя последняя попытка была

use std::ops::Deref;

trait Tr<'a> {
    fn trim_indent(self) -> Deref<Target = str> + 'a + Sized;
}

impl<'a, T: AsRef<str>> Tr<'a> for T {
    fn trim_indent(self) -> Deref<Target = str> + 'a + Sized {
        self.as_ref()[..1] // some transformation here
    }
}

fn main() {
    let s = "aaa".trim_indent();
    println!("{}", s);
}

Я застрял, потому что без Sized я получаю ошибку, тип которой неизвестен во время компиляции, но с Size я получаю ошибку, что не могу явно использовать маркерную черту,

1 Ответ

0 голосов
/ 22 мая 2018

Независимо от того, с какого типа вы начинаете, конечным типом нарезки &str всегда является &str, поэтому ваш тип возвращаемого значения должен быть &str.

Тогда вопрос реализациичерта для ссылок на тип, так что вы можете связать время жизни ввода и вывода вместе:

use std::rc::Rc;

trait Tr<'a> {
    fn trim_indent(self) -> &'a str;
}

impl<'a, T> Tr<'a> for &'a T
where
    T: AsRef<str> + 'a,
{
    fn trim_indent(self) -> &'a str {
        &self.as_ref()[..1] // Take the first **byte**
    }
}

fn main() {
    let s: &str = "aaa";
    println!("{}", s.trim_indent());

    let s: Box<str> = Box::from("bbb");
    println!("{}", s.trim_indent());

    let s: Rc<str> = Rc::from("ccc");
    println!("{}", s.trim_indent());
}

В этом случае, поскольку все перечисленные вами типы реализуют Derefв любом случае, вы можете просто реализовать черту для &str, и все типы могут использовать ее:

trait Tr {
    fn trim_indent(&self) -> &str;
}

impl Tr for str {
    fn trim_indent(&self) -> &str {
        &self[..1]
    }
}

См. также:

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...