当我在Rust操场上运行以下代码时...
fn take_part_1<'a>(s: &'a str) -> &'a str {
s.split(':').next().unwrap()
}
fn take_part_2<'a, T: 'a + AsRef<str>>(s: &'a T) -> &'a str {
let b = s.as_ref().split(':').next().unwrap();
b
}
fn main() {
println!("{}", take_part_1("a:b"));
println!("{}", take_part_2("a:b"));
}
...编译器返回没有意义的错误:
12 | println!("{}", take_part_2("a:b"));
| ^^^^^^^^^^^ doesn't have a size known at compile-time
|
= help: the trait `std::marker::Sized` is not implemented for `str`
我可以这样添加来修复它?Sized
:
fn take_part_2<'a, T: 'a + AsRef<str> + ?Sized>(s: &'a T) -> &'a str {
为什么?Sized
需要这样做(为什么编译器将错误指向函数调用)?它有什么作用?我是否应该能够将引用传递给未缩放的对象并使其正常工作?
令我感到困惑的是,非通用实现按您的预期工作,没有任何要求?Sized
(即使编译器指出str不是Sized
!)
在大多数使用类型参数的地方,Rust会隐式插入一个附加Sized
界限。那是因为这是最常见的情况-如果它不以这种方式运行,那么您将不得不在任何地方写装订自己,这样会造成重复和嘈杂。
例如,您的take_part
函数与此完全相同:
fn take_part_2<'a, T: 'a + AsRef<str> + Sized>(s: &'a T) -> &'a str {
let b = s.as_ref().split(':').next().unwrap();
b
}
然而,你的函数的实现并不需要T
是Sized
因为它只是有史以来参考使用它。: ?Sized
有效地添加将消除该隐式边界,并向类型检查器传达T
不需要知道其大小的信息,因此您的功能应尽可能通用。在这种情况下,使其更具通用性,则可以使用动态大小类型T
as调用它str
。
本文收集自互联网,转载请注明来源。
如有侵权,请联系[email protected] 删除。
我来说两句