2017-02-26 97 views
2

下面是修改后的版本的example of usage Deref符合:Deref和mark运算符,为什么它们不一样?

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

#[derive(Clone, PartialEq, Hash, PartialOrd, Eq, Ord)] 
pub struct InternedString { 
    string: Rc<String>, 
} 

impl InternedString { 
    #[inline] 
    pub fn new(string: &'static str) -> InternedString { 
     InternedString { 
      string: Rc::new(string.to_owned()), 
     } 
    } 
} 

impl Deref for InternedString { 
    type Target = str; 

    fn deref(&self) -> &str { &self.string } 
} 


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); 

    match *x { 
     'a' =>(), 
     _ =>(), 
    }; 

    let s = InternedString::new("aaa"); 
    match *s { 
     "test" =>(), 
     _ =>(), 
    }; 
} 

它没有被编译,错误:

55 |   "test" =>(), 
    |   ^^^^^^ expected str, found reference 
    | 
    = note: expected type `str` 
    = note: found type `&'static str` 

,但如果我叫deref方法,通过手:

match s.deref() { 
    "test" =>(), 
    _ =>(), 
} 

所有编译没有错误,*ss.deref()之间有什么区别,为什么对于char所有工作正常?

回答

4

字符文字的类型为char,而字符串文字的类型为&'static str。请注意,字符串文字总是引用,而字符文字不是引用。

*s实际上转换为*(s.deref()),不s.deref(),执行DEREF胁迫时,因为deref返回一个引用。因此,要将InternedString与字符串文字匹配,您需要参考*s,即您需要编写&*s而不是*s。这是有效的,因为*s产生一个左值。

+0

但实际上'Deref'特征超载'&'? – user1244932

+0

不,'Deref'真的重载'*',但编译器可以在上下文需要时隐式插入'*'。例如,如果你编写'&s',编译器可能会把它翻译成'&* s',然后它可以转换为'&*(s.deref())'(这简化为's.deref() ')。 –

相关问题