如何实现一个方法来使用 &str、Box<str>、Rc <str>等?



我有以某种方式转换字符串引用的代码,例如取第一个字母

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,我得到一个错误,我无法显式使用标记特征。

无论您从哪种类型开始,切片&str的结束类型始终是&str,因此您的返回类型需要是一个&str

然后,需要实现对类型的引用的 trait,以便可以将输入和输出生存期绑定在一起:

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

另请参阅:

  • 为什么在 Rust 中将字符串的第一个字母大写如此复杂?

最新更新