问号在类型参数绑定中意味着什么?

我找到了 std::borrow::BorrowMut的定义:

pub trait BorrowMut<Borrowed>: Borrow<Borrowed>
where
Borrowed: ?Sized,
{
fn borrow_mut(&mut self) -> &mut Borrowed;
}

在这个类型参数绑定(Borrowed: ?Sized)中,Sized前面的问号是什么意思?

我咨询过:

但是没有找到合理的解释。请在你的回答中提供参考。


特别参见5.20 Traits 部分

2 和 section < a href = “ https://doc.ust-lang.org/Reference.html # trait”rel = “ noReferrer”> 6.1.9 Traits

9640 次浏览

这意味着 trait 是 可以选择。当前的语法是在 语法 RFC中引入的。

我所知道的适用于 ?的唯一特性是 Sized

在这个特定的示例中,我们可以为 身材矮小的人实现 BorrowMut,就像 [T]ーー注意,这里没有 &

一个内置的实现利用了这一点:

impl<T> BorrowMut<[T]> for Vec<T>

作为 马修 · M 补充道:

这是 扩大范围的情况; 一般情况下,限制 更多,但在 Sized的情况下,决定除非另有说明,否则将假定一般 TSized。注意到相反情况的方法是将其标记为 ?Sized(“可能是 Sized”)。

这里是另一种解释,基于一个例子,这可能有助于理解的概念,这已经非常准确地解释了谢普马斯特和马蒂厄。

假设我们想用 一般实现创建一个 trait,如下所示:

pub trait MyTrait<T> {
fn say_hi(&self) -> String;
}


impl<T> MyTrait<T> for &T {
fn say_hi(&self) -> String {
return "Hi!".to_string();
}
}

这将允许我们在引用各种类型时调用 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());

但是,如果我们像这样声明一个函数:

fn be_fancy(arr: &[u16]) {
println!("arr: {}", arr.say_hi());
}

,我们将得到一个编译器错误:

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`

可以看出,问题在于我们的 trait 只在引用 Sized类型时实现。Sized是一种特殊的 记号笔特性,默认情况下是“打开”的。在大多数情况下,这很方便,但有时我们可能想要关闭这种“限制”。?Sized基本上说的是“该类型可能是或可能不是大小”(这与“不大小”是不一样的)。

我们的函数 be_fancy需要对 未知(在编译时)大小的数组的引用。为了解决这个问题,我们可以简单地用 T: ?Sized代替 T(相当于 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();
}
}