Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/opencv/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Syntax 什么是';其中';特征中的子句是什么?_Syntax_Rust_Traits_Type Bounds - Fatal编程技术网

Syntax 什么是';其中';特征中的子句是什么?

Syntax 什么是';其中';特征中的子句是什么?,syntax,rust,traits,type-bounds,Syntax,Rust,Traits,Type Bounds,如果我有此代码: 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:size规定了实现Trait类

如果我有此代码:

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:size
规定了实现
Trait
类型的一些内容,比如“如果你为
A
类型实现
Trait
,那么你的
A
类型必须调整大小,也就是说,它可以是
i32
,但不能是
[i32]

然而,这样的约束更像是
trait:size
(如果我错了,请纠正我)

现在我注意到
中Self:size
实际上决定了我是否可以从
object\u safety\u dynamic
中调用
f
g

我的问题是:

  • 在幕后发生了什么

  • 我通过
    where Self:Sized告诉编译器什么(用简单的英语说)使
    g()
    工作,但
    f()
    不工作

  • 特别是:由于
    &self
    无论如何都是一个参考,不同类型(大小或非大小)的
    f
    g
    之间存在什么编译差异。不管
    在哪里
    ,或者类型大小与否,它都会归结为类似于
    的东西吗

  • 为什么我可以同时为
    u8
    [u8]
    实现Trait。编译器不应该阻止我为
    [u8]
    实现
    f()
    ,而不是在调用站点抛出错误吗

  • fn f(&self)->i32,其中self:size

    这意味着
    f
    仅为同样实现
    大小的类型定义。未分级的类型仍然可以实现
    Trait
    ,但
    f
    将不可用

    object\u safety\u dynamic
    内部,调用
    x.f()
    实际上是在做:
    (*x.f()
    )。虽然
    x
    的大小是因为它是指针,但
    *x
    可能不是,因为它可能是
    Trait
    的任何实现。但是函数中的代码必须适用于任何有效参数,因此不允许在那里调用
    x.f()

    where子句实际上是做什么的

    天真地,我在想自我:大小;指示有关类型实现特征的内容,例如“如果为类型A实现特征,则必须调整类型A的大小,即它可以是i32,但不能是[i32]

    然而,这样的约束更像是trait:size

    这是正确的

    但是,在这种情况下,边界仅适用于函数<代码>其中
    仅在调用站点检查函数的边界

    在幕后发生了什么

    rust的语法有一点让人困惑,那就是
    Trait
    可以引用其中任何一种

    • 特质
      特质
      ;或
    • “trait对象”
      trait
      ,它实际上是一个类型,而不是一个对象
    size
    是一种特性,任何
    T
    类型的
    size
    都可以通过
    std::mem::size_of:()
    将其大小作为常量。未调整大小的类型有
    str
    [u8]
    ,它们的内容没有固定的大小

    类型
    Trait
    也没有大小。直观地说,这是因为
    Trait
    作为一个类型,由实现Trait
    Trait
    的所有类型值组成,这些值的大小可能不同。这意味着您永远不能拥有
    Trait
    类型的值-您只能通过“胖指针”引用一个值,例如
    &Trait
    等。它们有两个指针大小——一个用于vtable,一个用于数据。大致如下:

    struct &Trait {
        pub data: *mut (),
        pub vtable: *mut (),
    }
    
    自动生成以下表单的impl:

    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:size;这使得g()工作,但f()不工作

    请注意,正如我所提到的,
    Trait
    不是
    size
    ,因此绑定的
    Self:size
    不满足,因此不能在
    Self==Trait
    的位置调用函数
    f

    特别是:既然&self无论如何都是一个引用,那么对于各种类型(大小或未大小),f和g之间存在什么不同。无论类型在何处或大小是否相同,它是否总是可以归结为类似于_vtable_f_或_g(*self)->i32的东西

    类型
    Trait
    始终未调整大小。哪种类型被强制为
    Trait
    ,并不重要。使用
    size
    变量调用函数的方法是直接使用它:

    fn generic<T: Trait + Sized>(x: &T) { // the `Sized` bound is implicit, added here for clarity
        x.f();  // compiles just fine
        x.g();
    }
    
    fn generic(x:&T){//为清晰起见,此处添加的'size'边界是隐式的
    x、 f();//编译得很好
    x、 g();
    }
    
    为什么我可以为u8和[u8]实现Trait。编译器不应该阻止我为[u8]实现f(),而不是在调用站点抛出错误吗


    因为特征不受自身大小的限制,所以函数
    f
    是。因此,没有什么可以阻止您实现该函数-只是函数的边界永远无法满足,因此您永远无法调用它。

    我认为您的
    f
    g
    方法是错误的
    x.g()
    应该可以工作,而
    x.f()
    将是一个错误。这是因为
    f
    仅为
    size
    的类型定义,但不能保证
    x
    size
    的,因为
    Trait
    impl
    并非所有的
    s都是。对Trait的约束限制了哪些类型可以实现Trait。将函数的约束放在trait中会限制实现类型可以调用函数。@PeterHall,是的,谢谢!