我有以某种方式转换字符串引用的代码,例如取第一个字母
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 中将字符串的第一个字母大写如此复杂?