我找到了以下定义std::borrow::BorrowMut:
pub trait BorrowMut<Borrowed>: Borrow<Borrowed>
where
Borrowed: ?Sized,
{
fn borrow_mut(&mut self) -> &mut Borrowed;
}
Run Code Online (Sandbox Code Playgroud)
Sized在这个类型参数bound(Borrowed: ?Sized)中,问号前面的问号是什么?
我咨询过:
但没有找到解释.请在答案中提供参考.
She*_*ter 35
这意味着特征是可选的.当前语法是在DST语法RFC中引入的.
我所知道的唯一特征?是Sized.
在这个具体的例子,我们可以实现BorrowMut对未分级的类型,就像[T]-请注意,有没有&在这里!
一个内置实现利用了:
impl<T> BorrowMut<[T]> for Vec<T>
Run Code Online (Sandbox Code Playgroud)
这是一个扩大的范围 ; 一般而言,限制会产生更多的限制,但在
Sized决定的情况下,除非另有说明,否则T将假定通用Sized.注意相反的方法是标记它?Sized("可能Sized").
at5*_*321 18
这是基于示例的另一种解释,可能有助于理解这个概念,谢普马斯特和马蒂厄已经非常准确地解释了这个概念。
假设我们想要使用如下通用实现来创建一个特征:
pub trait MyTrait<T> {
fn say_hi(&self) -> String;
}
impl<T> MyTrait<T> for &T {
fn say_hi(&self) -> String {
return "Hi!".to_string();
}
}
Run Code Online (Sandbox Code Playgroud)
这将使我们能够调用say_hi()对各种类型的引用,如下所示:
let a = &74; // a reference to a SIZED integer
println!("a: {}", a.say_hi());
let b = &[1, 2, 3]; // a reference to a SIZED array
println!("b: {}", b.say_hi());
Run Code Online (Sandbox Code Playgroud)
但是,如果我们声明一个这样的函数:
fn be_fancy(arr: &[u16]) {
println!("arr: {}", arr.say_hi());
}
Run Code Online (Sandbox Code Playgroud)
,我们会得到一个编译器错误:
error[E0599]: the method `say_hi` exists for reference `&[u16]`, but its trait bounds were not satisfied
|
| println!("arr: {}", arr.say_hi());
| ^^^^^^ method cannot be called on `&[u16]` due to unsatisfied trait bounds
|
note: the following trait bounds were not satisfied because of the requirements of the implementation of `MyTrait<_>` for `_`:
`[u16]: Sized`
Run Code Online (Sandbox Code Playgroud)
可以看出,问题是我们的特征仅针对Sized类型的引用而实现。Sized是默认情况下“打开”的特殊标记特征。在大多数情况下这很方便,但有时我们可能想关闭该“限制”。?Sized基本上是说“类型可能会或可能不会调整大小”(这与“未调整大小”不同)。
我们的函数be_fancy需要引用一个未知(在编译时)大小的数组。要解决这个问题,我们可以简单地将T(相当于T: Sized)替换为T: ?Sized:
pub trait MyTrait<T: ?Sized> {
fn say_hi(&self) -> String;
}
impl<T: ?Sized> MyTrait<T> for &T {
fn say_hi(&self) -> String {
return "Hi yo!".to_string();
}
}
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
3473 次 |
| 最近记录: |