特征中的“ where”子句有什么作用?

left4bread

如果我有此代码:

trait Trait {
    fn f(&self) -> i32 where Self: Sized;

    fn g(&self) -> i32;
}


fn object_safety_dynamic(x: &Trait) {
    x.f();    // error 
    x.g();    // works
}

where条款实际上是做什么的?

天真,我在想where Self: Sized;使然一些关于类型实现Trait,像“如果实现Trait类型A的类型A必须调整,即,它可以i32但不是[i32]

但是,这样的约束宁可去trait Trait: Sized(如果我错了,纠正我)?

现在我注意到where Self: Sized;实际上确定了是否可以打电话fg从内打电话object_safety_dynamic

我的问题:

  1. 幕后发生了什么?

  2. 我实际上是在告诉编译器什么(用简单的英语)where Self: Sized;g()f()没有奏效

  3. 特别是:由于&self无论如何都是参考,因此在各种(大小或未大小)类型之间f以及g对于各种(大小或未大小)类型,已编译的差异存在_vtable_f_or_g(*self) -> i32不管where类型是否大小它是否总会归结为类似的东西

  4. 为什么我要为u8都实施Trait [u8]编译器是否应该实际上阻止我实施f()for [u8],而不是在调用站点上抛出错误?

Djzin

where子句实际上是做什么的?

天真的,我在想Self:Sized; 规定了有关实现Trait的类型的某些内容,例如,“如果您为Type A实现Trait,则您的Type A必须是大小,即可以是i32,但不能为[i32]。

但是,这样的约束更适合作为特征:特质

这是对的。

但是,在这种情况下,界限仅适用于该功能。where仅在呼叫站点上检查功能范围。

幕后发生了什么?

关于rust的语法有一个令人困惑的地方,那就是Trait可以引用

  • 特质Trait; 要么
  • “特征对象”Trait实际上是一种类型,而不是对象。

Sized是一个特征,任何类型的大小TSized可以通过来作为常量std::mem::size_of::<T>()此类没有大小的类型是str[u8],其内容的大小没有固定的大小。

该类型Trait也没有大小。直观地讲,这是因为Trait作为一个类型,它包含实现trait的类型的所有值Trait,它们的大小可能有所不同。这意味着您永远不会拥有类型的值Trait-您只能通过“胖指针”(例如&TraitorBox<Trait>等等)引用一个值它们的大小为2个指针-一个用于vtable,一个用于数据。大致如下所示:

struct &Trait {
    pub data: *mut (),
    pub vtable: *mut (),
}

系统会自动提供以下形式的展示:

impl Trait /* the trait */ for Trait /* the type */ {
    fn f(&self) -> i32 where Self: Sized { .. }
    fn g(&self) -> i32 {
        /* vtable magic: something like (self.vtable.g)(self.data) */
    }
}

我实际上是通过Self:Sized告诉编译器的是什么?这使g()有效,但f()不起作用?

请注意,由于正如我所提到Trait的那样SizedSelf: Sized不满足边界要求,因此f不能在where调用该函数Self == Trait

特别是:由于&self仍然是引用,因此对于各种(大小或未大小大小)类型,f和g之间存在已编译的差异。不管类型在何处或是否在大小上,它是否总是会归结为_vtable_f_or_g(* self)-> i32之类的东西?

该类型Trait始终未上浆。强制类型无关紧要TraitSized使用变量调用函数的方式是直接使用它:

fn generic<T: Trait + Sized>(x: &T) { // the `Sized` bound is implicit, added here for clarity
    x.f();  // compiles just fine
    x.g();
}

为什么我要为u8和[u8]都实现Trait。编译器是否应该阻止我为[u8]实现f(),而不是在调用站点上抛出错误?

因为特征不受Self: Sized-函数f的限制。因此,没有什么可以阻止您实现该功能-只是永远无法满足该功能的界限,因此您永远无法调用它。

本文收集自互联网,转载请注明来源。

如有侵权,请联系 [email protected] 删除。

编辑于
0

我来说两句

0 条评论
登录 后参与评论

相关文章

为什么在where子句中存在特征绑定,而在函数签名中却没有?

框逆特征/框中的where子句

为什么where子句在熊猫中不起作用?

Rust中where子句中特征的可能运算符是什么?

Rust中的自动特征是什么?

特征库中的Transform :: linear()返回什么?

GLM 中 SparseMatrix 的等效特征是什么?

xgboost 中可能的特征类型有哪些?

访问特征中现有的ActorSystem

为什么我的WHERE子句在组合框中不起作用

为什么where子句查询在android的sqlite数据库中不起作用?

Scala中的通用特征有什么用?

为什么在Scala中没有“ Functor”特征?

Cakephp 3中的特征和行为有什么区别?

where子句在mysql中不起作用

如何在一个 ColumnTransformerr 中为所有类型的特征、分类特征和数值特征组合管道?

在WHERE子句字段中没有None的Django SQL查询不起作用

为什么可以在Scala中实例化多个特征,而不能实例化一个特征?

随机森林模型中具有递归特征消除的特征选择错误

没有从在Rust中实现特征的结构推断出的特征吗?

张量流中每个特征的有效多特征相似性

什么是自动编码器中的编码特征?是否有用于计算编码特征的公式?

推导模块中的可编码特征不起作用

Scala赋值运算符_ =在特征中不起作用

特征向量在Sympy中不起作用

为什么SELECT COUNT(*)比MySQL中带有WHERE子句的SELECT慢得多?

在Postgresql中,要在WHERE子句中传递什么以使列的枚举类型选择所有类型?

Linq 中 where 子句中的单个“=”与“==”运算符有什么区别 - C#

有没有办法在PHP中扩展特征?