【问题标题】:Why does asserting on the result of Deref::deref fail with a type mismatch?为什么断言 Deref::deref 的结果会因类型不匹配而失败?
【发布时间】:2015-06-01 05:55:17
【问题描述】:

以下是Deref example from The Rust Programming Language,除了我添加了另一个断言。

为什么assert_eqderef 也等于'a'?为什么我手动调用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");
}

如果我取消注释该行,我会收到此错误:

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)

【问题讨论】:

    标签: pointers rust


    【解决方案1】:

    首先,让我们为您的具体示例说明通用类型:'a'char,所以我们有:

    impl Deref for DerefExample<char> {
        type Target = char;
    
        fn deref(&self) -> &char {
            &self.value
        }
    }
    

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

    你问为什么deref 返回一个引用开头?不是圆形吗?嗯,不,它不是循环的:它减少库定义的智能指针指向编译器已经知道如何取消引用的内置类型&amp;T。通过返回一个引用而不是一个值,您可以避免复制/移动(这可能并不总是可能的!)并允许&amp;*x(或&amp;x,当它被强制时)引用实际 char DerefExample 持有而不是临时副本。

    另见:

    【讨论】:

    • 感谢您的回答。当您说“例如,* x 将调用 deref 并取消引用结果”时,我认为您的意思是实际上发生了两件事,首先调用 deref 以获取 (&) 引用,然后“取消引用”以获取访问权限到字符。
    猜你喜欢
    • 2015-10-15
    • 2020-08-28
    • 2018-03-11
    • 2014-11-06
    • 2019-08-05
    • 2021-09-22
    • 1970-01-01
    • 2020-05-27
    • 1970-01-01
    相关资源
    最近更新 更多