为什么对Deref :: deref的结果进行断言会因类型不匹配而失败? [英] Why does asserting on the result of Deref::deref fail with a type mismatch?

查看:96
本文介绍了为什么对Deref :: deref的结果进行断言会因类型不匹配而失败?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

以下是 Deref示例> Rust编程语言 ,除了我添加了另一个断言.

The following is the Deref example from The Rust Programming Language except I've added another assertion.

为什么assert_eqderef也等于'a'?手动调用deref后,为什么需要*?

Why does the assert_eq with the deref also equal 'a'? Why do I need a * once I've manually called deref?

use std::ops::Deref;

struct DerefExample<T> {
    value: T,
}

impl<T> Deref for DerefExample<T> {
    type Target = T;

    fn deref(&self) -> &T {
        &self.value
    }
}

fn main() {
    let x = DerefExample { value: 'a' };
    assert_eq!('a', *x.deref()); // this is true
    // assert_eq!('a', x.deref()); // this is a compile error
    assert_eq!('a', *x); // this is also true
    println!("ok");
}

如果我取消注释该行,则会出现此错误:

If I uncomment the line, I get this error:

error[E0308]: mismatched types
  --> src/main.rs:18:5
   |
18 |     assert_eq!('a', x.deref());
   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected char, found &char
   |
   = note: expected type `char`
              found type `&char`
   = help: here are some functions which might fulfill your needs:
           - .to_ascii_lowercase()
           - .to_ascii_uppercase()
   = note: this error originates in a macro outside of the current crate (in Nightly builds, run with -Z external-macro-backtrace for more info)

推荐答案

首先,让我们为您的特定示例拼写泛型类型:'a'char,所以我们有:

First, let's spell out the generic types for your specific example: 'a' is char, so we have:

impl Deref for DerefExample<char> {
    type Target = char;

    fn deref(&self) -> &char {
        &self.value
    }
}

值得注意的是,deref的返回类型是对char引用.因此,当仅使用x.deref()时,结果是&char而不是char,这也就不足为奇了.请记住,此时deref只是另一种常规方法-它只是作为某些语言提供的特殊语法的 part 隐式调用.例如,*x将调用deref并取消引用结果(如果适用). x.char_method()fn_taking_char(&x)也会多次调用deref,然后对结果做进一步的处理.

Notably, the return type of deref is a reference to a char. Thus it shouldn't be surprising that, when you use just x.deref(), the result is a &char rather than a char. Remember, at that point deref is just another normal method — it's just implicitly invoked as part of some language-provided special syntax. *x, for example, will call deref and dereference the result, when applicable. x.char_method() and fn_taking_char(&x) will also call deref some number of times and then do something further with the result.

为什么您要问deref为什么要返回引用?那不是通函吗?好吧,不是,这不是循环的:它减少库定义的智能指针,该指针指向编译器已经知道如何取消引用的内置类型&T.通过返回引用而不是值,可以避免复制/移动(这可能并不总是可能的!),并允许&*x(或强制执行时为&x)引用 actual char拥有DerefExample而不是临时副本.

Why does deref return a reference to begin with, you ask? Isn't that circular? Well, no, it isn't circular: it reduces library-defined smart pointers to the built-in type &T which the compiler already knows how to dereference. By returning a reference instead of a value, you avoid a copy/move (which may not always be possible!) and allow &*x (or &x when it's coerced) to refer to the actual char that DerefExample holds rather than a temporary copy.

另请参阅:

这篇关于为什么对Deref :: deref的结果进行断言会因类型不匹配而失败?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
相关文章
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆