简体   繁体   English

为什么我们需要为 &T 全面实施 Deref 特性?

[英]Why do we need the blanket implementation of Deref trait for &T?

Implementing Deref for smart pointers makes accessing the data behind them convenient, which is why they implement Deref.为智能指针实现 Deref 可以方便地访问它们背后的数据,这就是它们实现 Deref 的原因。 On the other hand, the rules regarding Deref and DerefMut were designed specifically to accommodate smart pointers.另一方面,有关 Deref 和 DerefMut 的规则是专门为适应智能指针而设计的。 Because of this, Deref should only be implemented for smart pointers to avoid confusion.正因为如此,Deref 应该只为智能指针实现以避免混淆。

I understand its usefulness,but I don't know what's the use of this blanket implementation of the Deref trait.我明白它的用处,但我不知道 Deref 特性的这种一揽子实现有什么用。

#[stable(feature = "rust1", since = "1.0.0")]
#[rustc_const_unstable(feature = "const_deref", issue = "88955")]
impl<T: ?Sized> const Deref for &T {
    type Target = T;

    #[rustc_diagnostic_item = "noop_method_deref"]
    fn deref(&self) -> &T {
        *self
    }
}

As the book says here https://doc.rust-lang.org/book/ch15-02-deref.html#treating-a-type-like-a-reference-by-implementing-the-deref-trait正如书上所说https://doc.rust-lang.org/book/ch15-02-deref.html#treating-a-type-like-a-reference-by-implementing-the-deref-trait

Without the Deref trait, the compiler can only dereference & references.如果没有 Deref 特性,编译器只能解引用 & 引用。 The deref method gives the compiler the ability to take a value of any type that implements Deref and call the deref method to get a & reference that it knows how to dereference. deref 方法使编译器能够获取实现 Deref 的任何类型的值,并调用 deref 方法来获取它知道如何取消引用的 & 引用。

Why do we need this blanket implementation of Deref trait for &T type if the compiler knows how to deference it?如果编译器知道如何推导它,为什么我们需要为 &T 类型全面实现 Deref 特性?

What are Rust's exact auto-dereferencing rules? Rust 的自动解引用规则是什么? this question does not answer my question, because my question is what is the use of this blanket implementation.这个问题没有回答我的问题,因为我的问题是这种一揽子实施有什么用。

Why is the return type of Deref::deref itself a reference? 为什么 Deref::deref 的返回类型本身就是一个引用? this question didn't solve my doubts either.这个问题也没有解决我的疑惑。 in the first answer the author did not explain why there is the blanket implementation of Deref trait for &T type.在第一个答案中,作者没有解释为什么 &T 类型会全面实施 Deref 特征。

I added the code from the author of the first answer, with my own modifications我添加了第一个答案的作者的代码,并进行了我自己的修改

Rust playground https://play.rust-lang.org/?version=stable&mode=debug&edition=2021&gist=25387e87ea7a7ef349df9e9b6671f6e7 Rust 游乐场https://play.rust-lang.org/?version=stable&mode=debug&edition=2021&gist=25387e87ea7a7ef349df9e9b6671f6e7

I added some comments to make sure I really got it我添加了一些评论以确保我真的明白了

use std::ops::Deref;
use std::rc::Rc;

fn foo<T: Deref<Target = i32>>(t: T) {
    println!("{}", *t);
    print_type_of(&t);
    print_type_of(&(*t));
    println!("-----------------");
}

fn main() {
    // Ok, because &i32 implements Deref<Target = i32>, so deref() return &i32 and the compiler can deref it again to get i32
    // Thanks to the blanket implementation
    foo(&100i32);
    // No, because &&i32.deref() return &&i32, so the compiler can't deref it twice to get i32
    foo(&&100i32);
    // Ok, because Box<i32> implements Deref<Target = i32>, so deref() return &i32 and the compiler can deref it again to get i32
    // But this has nothing to do with the blanket implementation of Deref for &T
    // Because Box is not a reference type
    foo(Box::new(42i32));
    // Ok, because Rc<i32> implements Deref<Target = i32>, so deref() return &i32 and the compiler can deref it again to get i32
    foo(Rc::new(5i32));
}

fn print_type_of<T>(_: &T) {
    println!("{}", std::any::type_name::<T>())
}

I'm not sure I understand your answer我不确定我是否理解你的回答

A Deref implementation exists for &T the same reason any trait exists: genericism.&T存在Deref实现的原因与任何特征存在的原因相同:通用性。

Even if the compiler knows how to dereference references innately because they are built-in to the language, the Deref implementation should still exist so &T can be used in a context that requires Deref .即使编译器知道如何天生取消引用引用,因为它们是语言的内置, Deref实现应该仍然存在,所以&T可以在需要Deref的上下文中使用。 Consider this function:考虑这个 function:

fn foo<T: Deref<Target = i32>>(t: T) {
    println!("{}", *t);
}

See it working on the playground ;看到它在操场上工作;

It can accept references, Box s, Rc s, etc. If the Deref implementation did not exist for references, then you could use the dereferencing operator * on it directly, but you could not pass it to this function that dereferences what is passed.它可以接受引用、 Box s、 Rc s 等。如果引用不存在Deref实现,则可以直接在其上使用取消引用运算符* ,但不能将其传递给取消引用所传递内容的 function。 That would be inconsistent and confusing for no reason.那会毫无理由地不一致和混乱。


I'm not sure what your example is supposed to prove;我不确定你的例子应该证明什么; it can't be compiled outside the standard library and your assessment of the types is incorrect ( Self is &T so self is of type &&T , which when dereferenced returns a &T , which matches the return type).它不能在标准库之外编译,并且您对类型的评估不正确( Self&T所以self是类型&&T ,当取消引用时返回一个&T ,它与返回类型匹配)。 Implementing an equivalent trait works just fine:实现一个等价的 trait 效果很好:

trait Deref {
    type Target: ?Sized;
    fn deref(&self) -> &Self::Target;
}

impl<T: ?Sized> Deref for &T {
    type Target = T;
    fn deref(&self) -> &T {
        *self
    }
}

See it working on the playground ;看到它在操场上工作;

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 通用特征的一揽子特征实现 - blanket trait implementation for generic trait 在为闭包特征(Fn)创建整体实现时,为什么会得到“类型参数不受限制”的信息? - Why do I get “the type parameter is not constrained” when creating a blanket implementation for a closure trait (Fn)? 为什么这个一揽子特征实现的类型参数不被认为是受约束的? - Why is the type parameter of this blanket trait implementation not considered to be constrained? 覆盖 Rust 中的一揽子特征实现 - Overriding a blanket trait implementation in Rust 为什么我不能在带有类型参数的特征上添加一个全面的实现? - Why can't I add a blanket impl on a trait with a type parameter? 为什么需要定义特征来定义外部类型的实现? - Why do I need to define a trait to define an implementation on an external type? 如何使用毯子 Into 特征实现转换回原始类型? - How do I use the blanket Into trait implementation to convert back to the original type? 使用特征毯实现来限制 Rust 中的类型特征边界? - Use trait blanket implementation to restrict type trait bounds in Rust? 全面实施受本地定义的公共性状约束的核心性状 - Blanket implementation of core traits constrained by locally-defined public trait 为什么我们需要重复 trait 定义中指定的 trait bound? - Why we need to repeat trait bounds that were specified in trait definitions?
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM